aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
AgeCommit message (Collapse)AuthorFilesLines
2022-12-08analyzer: handle memmove like memcpyDavid Malcolm1-6/+12
gcc/analyzer/ChangeLog: * region-model-impl-calls.cc (class kf_memcpy): Rename to... (class kf_memcpy_memmove): ...this. (kf_memcpy::impl_call_pre): Rename to... (kf_memcpy_memmove::impl_call_pre): ...this, and check the src for poison. (register_known_functions): Update for above renaming, and register BUILT_IN_MEMMOVE and BUILT_IN_MEMMOVE_CHK. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/memcpy-1.c (test_8a, test_8b): New tests. * gcc.dg/analyzer/memmove-1.c: New test, based on memcpy-1.c * gcc.dg/analyzer/out-of-bounds-1.c (test7): Update expected result for uninit srcBuf. * gcc.dg/analyzer/out-of-bounds-5.c (test8, test9): Add dg-warnings for memcpy from uninit src vla. * gcc.dg/analyzer/pr104308.c (test_memmove_within_uninit): Expect creation point note to be missing on riscv*-*-*. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-07Daily bump.GCC Administrator1-0/+64
2022-12-06analyzer: don't create bindings or binding keys for empty regions [PR107882]David Malcolm6-9/+55
PR analyzer/107882 reports an ICE, due to trying to get a compound svalue for this binding: cluster for: a: key: {bytes 0-3} value: {UNKNOWN()} key: {empty} value: {UNKNOWN()} key: {bytes 4-7} value: {UNKNOWN()} where there's an binding to the unknown value of zero bits in size "somewhere" within "a" (perhaps between bits 3 and 4?) This makes no sense, so this patch adds an assertion that we never attempt to create a binding key for an empty region, and adds early rejection of attempts to get or set the values of such regions, fixing the ICE. gcc/analyzer/ChangeLog: PR analyzer/107882 * region-model.cc (region_model::get_store_value): Return an unknown value for empty regions. (region_model::set_value): Bail on empty regions. * region.cc (region::empty_p): New. * region.h (region::empty_p): New decl. * state-purge.cc (same_binding_p): Bail if either region is empty. * store.cc (binding_key::make): Assert that a concrete binding's bit_size must be > 0. (binding_cluster::mark_region_as_unknown): Bail on empty regions. (binding_cluster::get_binding): Likewise. (binding_cluster::remove_overlapping_bindings): Likewise. (binding_cluster::on_unknown_fncall): Don't conjure values for empty regions. (store::fill_region): Bail on empty regions. * store.h (class concrete_binding): Update comment to reflect that the range of bits must be non-empty. (concrete_binding::concrete_binding): Assert that bit range is non-empty. gcc/testsuite/ChangeLog: PR analyzer/107882 * gcc.dg/analyzer/memcpy-pr107882.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-06analyzer: use __attribute__((nonnull)) at top level of analysis [PR106325]David Malcolm4-5/+40
PR analyzer/106325 reports false postives from -Wanalyzer-null-dereference on code like this: __attribute__((nonnull)) void foo_a (Foo *p) { foo_b (p); switch (p->type) { /* ... */ } } where foo_b (p) has a: g_return_if_fail (p); that expands to: if (!p) { return; } The analyzer "sees" the comparison against NULL in foo_b, and splits the analysis into the NULL and not-NULL cases; later, back in foo_a, at switch (p->type) it complains that p is NULL. Previously we were only using __attribute__((nonnull)) as something to complain about when it was violated; we weren't using it as a source of knowledge. This patch fixes things by making the analyzer respect __attribute__((nonnull)) at the top-level of the analysis: any such params are now assumed to be non-NULL, so that the analyzer assumes the g_return_if_fail inside foo_b doesn't fail when called from foo_a Doing so fixes the false positives. gcc/analyzer/ChangeLog: PR analyzer/106325 * region-model-manager.cc (region_model_manager::get_or_create_null_ptr): New. * region-model-manager.h (region_model_manager::get_or_create_null_ptr): New decl. * region-model.cc (region_model::on_top_level_param): Add "nonnull" param and make use of it. (region_model::push_frame): When handling a top-level entrypoint to the analysis, determine which params __attribute__((nonnull)) applies to, and pass to on_top_level_param. * region-model.h (region_model::on_top_level_param): Add "nonnull" param. gcc/testsuite/ChangeLog: PR analyzer/106325 * gcc.dg/analyzer/attr-nonnull-pr106325.c: New test. * gcc.dg/analyzer/attribute-nonnull.c (test_6): New. (test_7): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-06analyzer: split out more stuff from region-model-impl-calls.ccDavid Malcolm14-662/+822
gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Add analyzer/call-details.o, analyzer/kf-analyzer.o, and kf-lang-cp.o. gcc/analyzer/ChangeLog: * analyzer.h (register_known_analyzer_functions): New decl. (register_known_functions_lang_cp): New decl. * call-details.cc: New file, split out from region-model-impl-calls.cc. * call-details.h: New file, split out from region-model.h. * call-info.cc: Include "analyzer/call-details.h". * call-summary.h: Likewise. * kf-analyzer.cc: New file, split out from region-model-impl-calls.cc. * kf-lang-cp.cc: Likewise. * known-function-manager.cc: Include "analyzer/call-details.h". * region-model-impl-calls.cc: Move definitions of call_details's member functions to call-details.cc. Move class kf_analyzer_* to kf-analyzer.cc. Move kf_operator_new and kf_operator_delete to kf-lang-cp.cc. Refresh #includes accordingly. (register_known_functions): Replace registration of __analyzer_* functions with a call to register_known_analyzer_functions. Replace registration of C++ support functions with a call to register_known_functions_lang_cp. * region-model.h (class call_details): Move to new call-details.h. * sm-fd.cc: Include "analyzer/call-details.h". * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * varargs.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: Include "analyzer/call-details.h". * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-03Daily bump.GCC Administrator1-0/+85
2022-12-02analyzer: introduce struct event_loc_infoDavid Malcolm15-197/+211
gcc/analyzer/ChangeLog: * analyzer.h (struct event_loc_info): New forward decl. * bounds-checking.cc: Use event_loc_info throughout to bundle the loc, fndecl, depth triples. * call-info.cc: Likewise. * checker-event.cc: Likewise. * checker-event.h (struct event_loc_info): New decl. Use it throughout to bundle the loc, fndecl, depth triples. * checker-path.cc: Likewise. * checker-path.h: Likewise. * diagnostic-manager.cc: Likewise. * engine.cc: Likewise. * infinite-recursion.cc: Likewise. * pending-diagnostic.cc: Likewise. * pending-diagnostic.h: Likewise. * region-model.cc: Likewise. * sm-signal.cc: Likewise. * varargs.cc: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-02analyzer: fixes to region creation messages [PR107851]David Malcolm12-166/+237
In r13-2573-gc81b60b8c6ff3d I split up the analyzer's region-creation events to describe the memory space and capacity of the region as two separate events to avoid combinatorial explosion of message wordings. However I didn't take into account r13-1405-ge6c3bb379f515b which added a pending_diagnostic::describe_region_creation_event vfunc which could change the wording of region creation events. Hence for: #include <stdlib.h> #include <stdint.h> void test () { int32_t *ptr = malloc (1); free (ptr); } trunk currently emits: Compiler Explorer (x86_64 trunk): https://godbolt.org/z/e3Td7c9s5: <source>: In function 'test': <source>:6:18: warning: allocated buffer size is not a multiple of the pointee's size [CWE-131] [-Wanalyzer-allocation-size] 6 | int32_t *ptr = malloc (1); | ^~~~~~~~~~ 'test': events 1-3 | | 6 | int32_t *ptr = malloc (1); | | ^~~~~~~~~~ | | | | | (1) allocated 1 bytes here | | (2) allocated 1 bytes here | | (3) assigned to 'int32_t *' {aka 'int *'} here; 'sizeof (int32_t {aka int})' is '4' | where events (1) and (2) are different region_creation_events that have had their wording overridden (also, with a "1 bytes" issue). This patch reorganizes region creation events so that each pending_diagnostic instead creates the events that is appropriate for it, and the events have responsibility for their own wording. With this patch, the above emits: <source>: In function 'test': <source>:6:18: warning: allocated buffer size is not a multiple of the pointee's size [CWE-131] [-Wanalyzer-allocation-size] 6 | int32_t *ptr = malloc (1); | ^~~~~~~~~~ 'test': events 1-2 | | 6 | int32_t *ptr = malloc (1); | | ^~~~~~~~~~ | | | | | (1) allocated 1 byte here | | (2) assigned to 'int32_t *' {aka 'int *'} here; 'sizeof (int32_t {aka int})' is '4' | fixing the duplicate event, and fixing the singular/plural issue. gcc/analyzer/ChangeLog: PR analyzer/107851 * analyzer.cc (make_label_text_n): Convert param "n" from int to unsigned HOST_WIDE_INT. * analyzer.h (make_label_text_n): Likewise for decl. * bounds-checking.cc: Include "analyzer/checker-event.h" and "analyzer/checker-path.h". (out_of_bounds::add_region_creation_events): New. (concrete_past_the_end::describe_region_creation_event): Replace with... (concrete_past_the_end::add_region_creation_events): ...this. (symbolic_past_the_end::describe_region_creation_event): Delete. * checker-event.cc (region_creation_event::region_creation_event): Update for dropping all member data. (region_creation_event::get_desc): Delete, splitting out into region_creation_event_memory_space::get_desc, region_creation_event_capacity::get_desc, and region_creation_event_debug::get_desc. (region_creation_event_memory_space::get_desc): New. (region_creation_event_capacity::get_desc): New. (region_creation_event_allocation_size::get_desc): New. (region_creation_event_debug::get_desc): New. * checker-event.h: Include "analyzer/program-state.h". (enum rce_kind): Delete. (class region_creation_event): Drop all member data. (region_creation_event::region_creation_event): Make protected. (region_creation_event::get_desc): Delete. (class region_creation_event_memory_space): New. (class region_creation_event_capacity): New. (class region_creation_event_allocation_size): New. (class region_creation_event_debug): New. * checker-path.cc (checker_path::add_region_creation_events): Add "pd" param. Call pending_diangnostic::add_region_creation_events. Update for conversion of RCE_DEBUG to region_creation_event_debug. * checker-path.h (checker_path::add_region_creation_events): Add "pd" param. * diagnostic-manager.cc (diagnostic_manager::build_emission_path): Pass pending_diagnostic to emission_path::add_region_creation_events. (diagnostic_manager::build_emission_path): Pass path_builder to add_event_on_final_node. (diagnostic_manager::add_event_on_final_node): Add "pb" param. Pass pending_diagnostic to emission_path::add_region_creation_events. (diagnostic_manager::add_events_for_eedge): Pass pending_diagnostic to emission_path::add_region_creation_events. * diagnostic-manager.h (diagnostic_manager::add_event_on_final_node): Add "pb" param. * pending-diagnostic.cc (pending_diagnostic::add_region_creation_events): New. * pending-diagnostic.h (struct region_creation): Delete. (pending_diagnostic::describe_region_creation_event): Delete. (pending_diagnostic::add_region_creation_events): New vfunc. * region-model.cc: Include "analyzer/checker-event.h" and "analyzer/checker-path.h". (dubious_allocation_size::dubious_allocation_size): Initialize m_has_allocation_event. (dubious_allocation_size::describe_region_creation_event): Delete. (dubious_allocation_size::describe_final_event): Update for replacement of m_allocation_event with m_has_allocation_event. (dubious_allocation_size::add_region_creation_events): New. (dubious_allocation_size::m_allocation_event): Replace with... (dubious_allocation_size::m_has_allocation_event): ...this. gcc/testsuite/ChangeLog: PR analyzer/107851 * gcc.dg/analyzer/allocation-size-4.c: Update expected wording. * gcc.dg/analyzer/allocation-size-multiline-1.c: New test. * gcc.dg/analyzer/allocation-size-multiline-2.c: New test. * gcc.dg/analyzer/out-of-bounds-multiline-1.c: Update expected wording. * gcc.dg/analyzer/out-of-bounds-multiline-2.c: New test. * gcc.dg/analyzer/out-of-bounds-read-char-arr.c: Update expected wording. * gcc.dg/analyzer/out-of-bounds-read-int-arr.c: Likewise. * gcc.dg/analyzer/out-of-bounds-write-char-arr.c: Likewise. * gcc.dg/analyzer/out-of-bounds-write-int-arr.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-02Daily bump.GCC Administrator1-0/+124
2022-12-01analyzer: handle comparisons against negated symbolic values [PR107948]David Malcolm2-0/+16
gcc/analyzer/ChangeLog: PR analyzer/107948 * region-model-manager.cc (region_model_manager::maybe_fold_binop): Fold (0 - VAL) to -VAL. * region-model.cc (region_model::eval_condition): Handle e.g. "-X <= 0" as equivalent to X >= 0". gcc/testsuite/ChangeLog: PR analyzer/107948 * gcc.dg/analyzer/feasibility-pr107948.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: fix i18n issues in symbolic out-of-bounds [PR106626]David Malcolm1-54/+138
gcc/analyzer/ChangeLog: PR analyzer/106626 * bounds-checking.cc (symbolic_past_the_end::describe_final_event): Delete, moving to symbolic_buffer_overflow::describe_final_event and symbolic_buffer_over_read::describe_final_event, eliminating composition of text strings via "byte_str" and "m_dir_str". (symbolic_past_the_end::m_dir_str): Delete field. (symbolic_buffer_overflow::symbolic_buffer_overflow): Drop m_dir_str. (symbolic_buffer_overflow::describe_final_event): New, as noted above. (symbolic_buffer_over_read::symbolic_buffer_overflow): Drop m_dir_str. (symbolic_buffer_over_read::describe_final_event): New, as noted above. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: unify bounds-checking class hierarchiesDavid Malcolm2-94/+115
Convert out-of-bounds class hierarchy from: pending_diagnostic out_of_bounds past_the_end buffer_overflow (*) buffer_over_read (*) buffer_underwrite (*) buffer_under_read (*) symbolic_past_the_end symbolic_buffer_overflow (*) symbolic_buffer_over_read (*) to: pending_diagnostic out_of_bounds concrete_out_of_bounds concrete_past_the_end concrete_buffer_overflow (*) concrete_buffer_over_read (*) concrete_buffer_underwrite (*) concrete_buffer_under_read (*) symbolic_past_the_end symbolic_buffer_overflow (*) symbolic_buffer_over_read (*) where the concrete classes (i.e. the instantiable ones) are marked with a (*). Doing so undercovered a bug where, for CWE-131-examples.c, we were emitting an extra: warning: heap-based buffer over-read [CWE-122] [-Wanalyzer-out-of-bounds] at the: WidgetList[numWidgets] = NULL; The issue was that within set_next_state we get the rvalue for the LHS, which looks like a read to the bounds-checker. The patch fixes this by passing NULL as the region_model_context * for such accesses. gcc/analyzer/ChangeLog: * bounds-checking.cc (class out_of_bounds): Split out from... (class concrete_out_of_bounds): New abstract subclass. (class past_the_end): Rename to... (class concrete_past_the_end): ...this, and make a subclass of concrete_out_of_bounds. (class buffer_overflow): Rename to... (class concrete_buffer_overflow): ...this, and make a subclass of concrete_past_the_end. (class buffer_over_read): Rename to... (class concrete_buffer_over_read): ...this, and make a subclass of concrete_past_the_end. (class buffer_underwrite): Rename to... (class concrete_buffer_underwrite): ...this, and make a subclass of concrete_out_of_bounds. (class buffer_under_read): Rename to... (class concrete_buffer_under_read): ...this, and make a subclass of concrete_out_of_bounds. (class symbolic_past_the_end): Convert to a subclass of out_of_bounds. (symbolic_buffer_overflow::get_kind): New. (symbolic_buffer_over_read::get_kind): New. (region_model::check_region_bounds): Update for renamings. * engine.cc (impl_sm_context::set_next_state): Eliminate "new_ctxt", passing NULL to get_rvalue instead. (impl_sm_context::warn): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: more bounds-checking wording tweaks [PR106626]David Malcolm1-34/+99
This patch tweaks the wording of -Wanalyzer-out-of-bounds: * use the spellings/terminology of CWE: * replace "underread" with "under-read", as per: https://cwe.mitre.org/data/definitions/127.html * replace "overread" with "over-read" as per: https://cwe.mitre.org/data/definitions/126.html * replace "underflow" with "underwrite" as per: https://cwe.mitre.org/data/definitions/124.html * wherever known, specify the memory region of the bad access, so that it says e.g. "heap-based buffer over-read" or "stack-based buffer over-read" gcc/analyzer/ChangeLog: PR analyzer/106626 * bounds-checking.cc (out_of_bounds::get_memory_space): New. (buffer_overflow::emit): Use it. (class buffer_overread): Rename to... (class buffer_over_read): ...this. (buffer_over_read::emit): Specify which memory space the read is from, where known. Change "overread" to "over-read". (class buffer_underflow): Rename to... (class buffer_underwrite): ...this. (buffer_underwrite::emit): Specify which memory space the write is to, where known. Change "underflow" to "underwrite". (class buffer_underread): Rename to... (class buffer_under_read): Rename to... (buffer_under_read::emit): Specify which memory space the read is from, where known. Change "underread" to "under-read". (symbolic_past_the_end::get_memory_space): New. (symbolic_buffer_overflow::emit): Use it. (class symbolic_buffer_overread): Rename to... (class symbolic_buffer_over_read): ...this. (symbolic_buffer_over_read::emit): Specify which memory space the read is from, where known. Change "overread" to "over-read". (region_model::check_symbolic_bounds): Update for class renaming. (region_model::check_region_bounds): Likewise. gcc/testsuite/ChangeLog: PR analyzer/106626 * gcc.dg/analyzer/call-summaries-2.c: Update expected results. * gcc.dg/analyzer/out-of-bounds-1.c: Likewise. * gcc.dg/analyzer/out-of-bounds-2.c: Likewise. * gcc.dg/analyzer/out-of-bounds-3.c: Likewise. * gcc.dg/analyzer/out-of-bounds-4.c: Likewise. * gcc.dg/analyzer/out-of-bounds-5.c: Likewise. * gcc.dg/analyzer/out-of-bounds-container_of.c: Likewise. * gcc.dg/analyzer/out-of-bounds-read-char-arr.c: Likewise. Rename functions from "int_arr_" to "char_arr_". * gcc.dg/analyzer/out-of-bounds-read-int-arr.c: Update expected results. * gcc.dg/analyzer/out-of-bounds-read-struct-arr.c: New test. * gcc.dg/analyzer/out-of-bounds-write-char-arr.c: Update expected results. Rename functions from "int_arr_" to "char_arr_". * gcc.dg/analyzer/out-of-bounds-write-int-arr.c: Update expected results. * gcc.dg/analyzer/out-of-bounds-write-struct-arr.c: New test. * gcc.dg/analyzer/pr101962.c: Update expected results. * gcc.dg/analyzer/realloc-5.c: Update expected results. * gcc.dg/analyzer/zlib-3.c: Update expected results. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: add note about valid subscripts [PR106626]David Malcolm1-4/+42
Consider -fanalyzer on: #include <stdint.h> int32_t arr[10]; void int_arr_write_element_after_end_off_by_one(int32_t x) { arr[10] = x; } Trunk x86_64: https://godbolt.org/z/17zn3qYY4 Currently we emit: <source>: In function 'int_arr_write_element_after_end_off_by_one': <source>:7:11: warning: buffer overflow [CWE-787] [-Wanalyzer-out-of-bounds] 7 | arr[10] = x; | ~~~~~~~~^~~ event 1 | | 3 | int32_t arr[10]; | | ^~~ | | | | | (1) capacity is 40 bytes | +--> 'int_arr_write_element_after_end_off_by_one': events 2-3 | | 5 | void int_arr_write_element_after_end_off_by_one(int32_t x) | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) entry to 'int_arr_write_element_after_end_off_by_one' | 6 | { | 7 | arr[10] = x; | | ~~~~~~~~~~~ | | | | | (3) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40 | <source>:7:11: note: write of 4 bytes to beyond the end of 'arr' 7 | arr[10] = x; | ~~~~~~~~^~~ This is worded in terms of bytes, due to the way -Wanalyzer-out-of-bounds is implemented, but this isn't what the user wrote. This patch tries to get closer to the user's code by adding a note about array bounds when we're referring to an array. In the above example it adds this trailing note: note: valid subscripts for 'arr' are '[0]' to '[9]' gcc/analyzer/ChangeLog: PR analyzer/106626 * bounds-checking.cc (out_of_bounds::maybe_describe_array_bounds): New. (buffer_overflow::emit): Call maybe_describe_array_bounds. (buffer_overread::emit): Likewise. (buffer_underflow::emit): Likewise. (buffer_underread::emit): Likewise. gcc/testsuite/ChangeLog: PR analyzer/106626 * gcc.dg/analyzer/call-summaries-2.c: Add dg-message for expected note about valid indexes. * gcc.dg/analyzer/out-of-bounds-1.c: Likewise, fixing up existing dg-message directives. * gcc.dg/analyzer/out-of-bounds-write-char-arr.c: Likewise. * gcc.dg/analyzer/out-of-bounds-write-int-arr.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: fix wording of 'number of bad bytes' note [PR106626]David Malcolm1-22/+44
Consider -fanalyzer on: #include <stdint.h> int32_t arr[10]; void int_arr_write_element_after_end_far(int32_t x) { arr[100] = x; } Trunk x86_64: https://godbolt.org/z/7GqEcYGq6 Currently we emit: <source>: In function 'int_arr_write_element_after_end_far': <source>:7:12: warning: buffer overflow [CWE-787] [-Wanalyzer-out-of-bounds] 7 | arr[100] = x; | ~~~~~~~~~^~~ event 1 | | 3 | int32_t arr[10]; | | ^~~ | | | | | (1) capacity is 40 bytes | +--> 'int_arr_write_element_after_end_far': events 2-3 | | 5 | void int_arr_write_element_after_end_far(int32_t x) | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) entry to 'int_arr_write_element_after_end_far' | 6 | { | 7 | arr[100] = x; | | ~~~~~~~~~~~~ | | | | | (3) out-of-bounds write from byte 400 till byte 403 but 'arr' ends at byte 40 | <source>:7:12: note: write is 4 bytes past the end of 'arr' 7 | arr[100] = x; | ~~~~~~~~~^~~ The wording of the final note: "write is 4 bytes past the end of 'arr'" reads to me as if the "4 bytes past" is describing where the access occurs, which seems wrong, as the write is far beyond the end of the array. Looking at the implementation, it's actually describing the number of bytes within the access that are beyond the bounds of the buffer. This patch updates the wording so that the final note reads "write of 4 bytes to beyond the end of 'arr'" which more clearly expresses that it's the size of the access being described. The patch also uses inform_n to avoid emitting "1 bytes". gcc/analyzer/ChangeLog: PR analyzer/106626 * bounds-checking.cc (buffer_overflow::emit): Use inform_n. Update wording to clarify that we're talking about the size of the bad access, rather than its position. (buffer_overread::emit): Likewise. gcc/testsuite/ChangeLog: PR analyzer/106626 * gcc.dg/analyzer/out-of-bounds-read-char-arr.c: Update for changes to expected wording. * gcc.dg/analyzer/out-of-bounds-read-int-arr.c: Likewise. * gcc.dg/analyzer/out-of-bounds-write-char-arr.c: Likewise. * gcc.dg/analyzer/out-of-bounds-write-int-arr.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: move bounds checking to a new bounds-checking.ccDavid Malcolm3-653/+697
gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Add analyzer/bounds-checking.o. gcc/analyzer/ChangeLog: * bounds-checking.cc: New file, taken from region-model.cc. * region-model.cc (class out_of_bounds): Move to bounds-checking.cc. (class past_the_end): Likewise. (class buffer_overflow): Likewise. (class buffer_overread): Likewise. (class buffer_underflow): Likewise. (class buffer_underread): Likewise. (class symbolic_past_the_end): Likewise. (class symbolic_buffer_overflow): Likewise. (class symbolic_buffer_overread): Likewise. (region_model::check_symbolic_bounds): Likewise. (maybe_get_integer_cst_tree): Likewise. (region_model::check_region_bounds): Likewise. * region-model.h: Add comment. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: fix ICE on bind/connect with a constant fd [PR107928]David Malcolm2-2/+10
gcc/analyzer/ChangeLog: PR analyzer/107928 * sm-fd.cc (fd_state_machine::on_bind): Handle m_constant_fd in the "success" outcome. (fd_state_machine::on_connect): Likewise. * sm-fd.dot: Add "constant_fd" state and its transitions. gcc/testsuite/ChangeLog: PR analyzer/107928 * gcc.dg/analyzer/fd-bind-pr107928.c: New test. * gcc.dg/analyzer/fd-connect-pr107928.c: New test. * gcc.dg/analyzer/fd-stream-socket-active-open.c (test_active_open_from_connect_constant): New, adapted from test_active_open_from_connect. * gcc.dg/analyzer/fd-stream-socket-passive-open.c (test_passive_open_from_bind_constant): New, adapted from test_passive_open_from_bind. (test_passive_open_from_listen_constant): New, adapted from test_passive_open_from_listen. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-01Daily bump.GCC Administrator1-0/+56
2022-11-29analyzer: move stdio known fns to sm-file.ccDavid Malcolm2-111/+106
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>
2022-11-29analyzer work on issues with flex-generated lexers [PR103546]David Malcolm5-0/+136
PR analyzer/103546 tracks various false positives seen on flex-generated lexers. Whilst investigating them, I noticed an ICE with -fanalyzer-call-summaries due to attempting to store sm-state for an UNKNOWN svalue, which this patch fixes. This patch also provides known_function implementations of all of the external functions called by the lexer, reducing the number of false positives. The patch doesn't eliminate all false positives, but adds integration tests to try to establish a baseline from which the remaining false positives can be fixed. gcc/analyzer/ChangeLog: PR analyzer/103546 * analyzer.h (register_known_file_functions): New decl. * program-state.cc (sm_state_map::replay_call_summary): Rejct attempts to store sm-state for caller_sval that can't have associated state. * region-model-impl-calls.cc (register_known_functions): Call register_known_file_functions. * sm-fd.cc (class kf_isatty): New. (register_known_fd_functions): Register it. * sm-file.cc (class kf_ferror): New. (class kf_fileno): New. (class kf_getc): New. (register_known_file_functions): New. gcc/ChangeLog: PR analyzer/103546 * doc/invoke.texi (Static Analyzer Options): Add isatty, ferror, fileno, and getc to the list of functions known to the analyzer. gcc/testsuite/ChangeLog: PR analyzer/103546 * gcc.dg/analyzer/ferror-1.c: New test. * gcc.dg/analyzer/fileno-1.c: New test. * gcc.dg/analyzer/flex-with-call-summaries.c: New test. * gcc.dg/analyzer/flex-without-call-summaries.c: New test. * gcc.dg/analyzer/getc-1.c: New test. * gcc.dg/analyzer/isatty-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-29analyzer: fix folding of '(PTR + 0) => PTR' [PR105784]David Malcolm1-4/+4
gcc/analyzer/ChangeLog: PR analyzer/105784 * region-model-manager.cc (region_model_manager::maybe_fold_binop): For POINTER_PLUS_EXPR, PLUS_EXPR and MINUS_EXPR, eliminate requirement that the final type matches that of arg0 in favor of a cast. gcc/testsuite/ChangeLog: PR analyzer/105784 * gcc.dg/analyzer/torture/fold-ptr-arith-pr105784.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-25Daily bump.GCC Administrator1-0/+88
2022-11-24analyzer: fix Clang warningsMartin Liska1-2/+2
Fixes the following warnings: gcc/analyzer/varargs.cc:655:8: warning: 'matches_call_types_p' overrides a member function but is not marked 'override' [-Winconsistent-missing-override] gcc/analyzer/varargs.cc:707:50: warning: unused parameter 'cd' [-Wunused-parameter] gcc/analyzer/varargs.cc:707:8: warning: 'matches_call_types_p' overrides a member function but is not marked 'override' [-Winconsistent-missing-override] gcc/analyzer/ChangeLog: * varargs.cc: Fix Clang warnings.
2022-11-23analyzer: revamp of heap-allocated regions [PR106473]David Malcolm8-25/+92
PR analyzer/106473 reports a false positive from -Wanalyzer-malloc-leak on: void foo(char **args[], int *argc) { *argc = 1; (*args)[0] = __builtin_malloc(42); } The issue is that at the write to *argc we don't know if argc could point within *args, and so we conservatiely set *args to be unknown. At the write "(*args)[0] = __builtin_malloc(42)" we have the result of the allocation written through an unknown pointer, so we mark the heap_allocated_region as having escaped. Unfortunately, within store::canonicalize we overzealously purge the heap allocated region, losing the information that it has escaped, and thus errnoeously report a leak. The first part of the fix is to update store::canonicalize so that it doesn't purge heap_allocated_regions that are marked as escaping. Doing so fixes the leak false positive, but leads to various state explosions relating to anywhere we have a malloc/free pair in a loop, where the analysis of the iteration appears to only have been reaching a fixed state due to a bug in the state merger code that was erroneously merging state about the region allocated in one iteration with that of another. On touching that, the analyzer fails to reach a fixed state on any loops containing a malloc/free pair, since each analysis of a malloc was creating a new heap_allocated_region instance. Hence the second part of the fix is to revamp how heap_allocated_regions are managed within the analyzer. Rather than create a new one at each analysis of a malloc call, instead we reuse them across the analysis, only creating a new one if the current path's state is referencing all of the existing ones. Hence the heap_allocated_region instances get used in a fixed order along every analysis path, so e.g. at: if (flag) p = malloc (4096); else p = malloc (1024); both paths now use the same heap_allocated_region for their malloc calls - but we still end up with two enodes after the CFG merger, by rejecting merger of states with non-equal dynamic extents. gcc/analyzer/ChangeLog: PR analyzer/106473 * call-summary.cc (call_summary_replay::convert_region_from_summary_1): Update for change to creation of heap-allocated regions. * program-state.cc (test_program_state_1): Likewise. (test_program_state_merging): Likewise. * region-model-impl-calls.cc (kf_calloc::impl_call_pre): Likewise. (kf_malloc::impl_call_pre): Likewise. (kf_operator_new::impl_call_pre): Likewise. (kf_realloc::impl_call_postsuccess_with_move::update_model): Likewise. * region-model-manager.cc (region_model_manager::create_region_for_heap_alloc): Convert to... (region_model_manager::get_or_create_region_for_heap_alloc): ...this, reusing an existing region if it's unreferenced in the client state. * region-model-manager.h (region_model_manager::get_num_regions): New. (region_model_manager::create_region_for_heap_alloc): Convert to... (region_model_manager::get_or_create_region_for_heap_alloc): ...this. * region-model.cc (region_to_value_map::can_merge_with_p): Reject merger when the values are different. (region_model::create_region_for_heap_alloc): Convert to... (region_model::get_or_create_region_for_heap_alloc): ...this. (region_model::get_referenced_base_regions): New. (selftest::test_state_merging): Update for change to creation of heap-allocated regions. (selftest::test_malloc_constraints): Likewise. (selftest::test_malloc): Likewise. * region-model.h: Include "sbitmap.h". (region_model::create_region_for_heap_alloc): Convert to... (region_model::get_or_create_region_for_heap_alloc): ...this. (region_model::get_referenced_base_regions): New decl. * store.cc (store::canonicalize): Don't purge a heap-allocated region that's been marked as escaping. gcc/testsuite/ChangeLog: PR analyzer/106473 * gcc.dg/analyzer/aliasing-pr106473.c: New test. * gcc.dg/analyzer/allocation-size-2.c: Add -fanalyzer-fine-grained". * gcc.dg/analyzer/allocation-size-3.c: Likewise. * gcc.dg/analyzer/explode-1.c: Mark leak with XFAIL. * gcc.dg/analyzer/explode-3.c: New test. * gcc.dg/analyzer/malloc-reuse.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-23analyzer: fix nondeterminism in logsDavid Malcolm1-2/+4
gcc/analyzer/ChangeLog: * checker-path.cc (checker_path::inject_any_inlined_call_events): Don't dump the address of the block when -fdump-noaddr. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-23analyzer: eliminate region_model::on_ fns for socketsDavid Malcolm2-100/+49
This mostly mechanical patch eliminates a confusing extra layer of redundant calls in the handling of socket-related functions. gcc/analyzer/ChangeLog: * region-model.h (region_model::on_socket): Delete decl. (region_model::on_bind): Likewise. (region_model::on_listen): Likewise. (region_model::on_accept): Likewise. (region_model::on_connect): Likewise. * sm-fd.cc (kf_socket::outcome_of_socket::update_model): Move body of region_model::on_socket into here, ... (region_model::on_socket): ...eliminating this function. (kf_bind::outcome_of_bind::update_model): Likewise for on_bind... (region_model::on_bind): ...eliminating this function. (kf_listen::outcome_of_listen::update_model): Likewise fo on_listen... (region_model::on_listen): ...eliminating this function. (kf_accept::outcome_of_accept::update_model): Likewise fo on_accept... (region_model::on_accept): ...eliminating this function. (kf_connect::outcome_of_connect::update_model): Likewise fo on_connect... (region_model::on_connect): ...eliminating this function. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-23analyzer: move known funs for fds to sm-fd.ccDavid Malcolm3-284/+296
This mostly mechanical change enables a simplification in the followup patch. No functional change intended. gcc/analyzer/ChangeLog: * analyzer.h (register_known_fd_functions): New decl. * region-model-impl-calls.cc (class kf_accept): Move to sm-fd.cc. (class kf_bind): Likewise. (class kf_connect): Likewise. (class kf_listen): Likewise. (class kf_pipe): Likewise. (class kf_socket): Likewise. (register_known_functions): Remove registration of the above functions, instead calling register_known_fd_functions. * sm-fd.cc: Include "analyzer/call-info.h". (class kf_socket): Move here from region-model-impl-calls.cc. (class kf_bind): Likewise. (class kf_listen): Likewise. (class kf_accept): Likewise. (class kf_connect): Likewise. (class kf_pipe): Likewise. (register_known_fd_functions): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-23Daily bump.GCC Administrator1-0/+195
2022-11-22analyzer: only look for named functions in root ns [PR107788]David Malcolm1-3/+12
gcc/analyzer/ChangeLog: PR analyzer/107788 * known-function-manager.cc (known_function_manager::get_match): Don't look up fndecls by name when they're not in the root namespace. gcc/testsuite/ChangeLog: PR analyzer/107788 * g++.dg/analyzer/named-functions.C: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-22analyzer: fix ICE on 'bind(INT_CST, ...)' [PR107783]David Malcolm1-3/+6
This was crashing inside fd_phase_mismatch's ctor with assertion failure when the state was "fd-constant". Fix the ICE by not complaining about constants passed to these APIs. gcc/analyzer/ChangeLog: PR analyzer/107783 * sm-fd.cc (fd_state_machine::check_for_new_socket_fd): Don't complain when old state is "fd-constant". (fd_state_machine::on_listen): Likewise. (fd_state_machine::on_accept): Likewise. gcc/testsuite/ChangeLog: PR analyzer/107783 * gcc.dg/analyzer/fd-accept.c (test_accept_on_constant): New. * gcc.dg/analyzer/fd-bind.c (test_bind_on_constant): New. * gcc.dg/analyzer/fd-connect.c (test_connect_on_constant): New. * gcc.dg/analyzer/fd-listen.c (test_listen_on_connected_socket): Fix typo. (test_listen_on_constant): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-22analyzer: fix 'errno' on Solaris and OS X [PR107807]David Malcolm1-0/+14
gcc/analyzer/ChangeLog: PR analyzer/107807 * region-model-impl-calls.cc (register_known_functions): Register "___errno" and "__error" as synonyms for "__errno_location". gcc/testsuite/ChangeLog: PR analyzer/107807 * gcc.dg/analyzer/errno-___errno.c: New test. * gcc.dg/analyzer/errno-__error.c: New test. * gcc.dg/analyzer/errno-global-var.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-22analyzer: eliminate region_model::impl_call_* special casesDavid Malcolm9-415/+648
Eliminate all of the remaining special cases in class region_model that handle various specific functions, replacing them with uses of known_function subclasses. Add various type-checks that ought to prevent ICEs for cases where functions match the name of a standard C library or POSIX function, but have incompatible arguments. gcc/analyzer/ChangeLog: * analyzer.h (class internal_known_function): New. (register_varargs_builtins): New decl. * engine.cc (exploded_node::on_stmt_pre): Remove "out_terminate_path" param from call to region_model::on_stmt_pre. (feasibility_state::maybe_update_for_edge): Likewise. * known-function-manager.cc: Include "basic-block.h", "gimple.h", and "analyzer/region-model.h". (known_function_manager::known_function_manager): Initialize m_combined_fns_arr. (known_function_manager::~known_function_manager): Clean up m_combined_fns_arr. (known_function_manager::get_by_identifier): Make const. (known_function_manager::add): New overloaded definitions for enum built_in_function and enum internal_fn. (known_function_manager::get_by_fndecl): Delete. (known_function_manager::get_match): New. (known_function_manager::get_internal_fn): New. (known_function_manager::get_normal_builtin): New. * known-function-manager.h (known_function_manager::get_by_identifier): Make private and add const qualifier. (known_function_manager::get_by_fndecl): Delete. (known_function_manager::add): Add overloaded decls for enum built_in_function name and enum internal_fn. (known_function_manager::get_match): New decl. (known_function_manager::get_internal_fn): New decl. (known_function_manager::get_normal_builtin): New decl. (known_function_manager::m_combined_fns_arr): New field. * region-model-impl-calls.cc (call_details::arg_is_size_p): New. (class kf_alloca): New. (region_model::impl_call_alloca): Convert to... (kf_alloca::impl_call_pre): ...this. (kf_analyzer_dump_capacity::matches_call_types_p): Rewrite check to use call_details::arg_is_pointer_p. (region_model::impl_call_builtin_expect): Convert to... (class kf_expect): ...this. (class kf_calloc): New, adding check that both arguments are size_t. (region_model::impl_call_calloc): Convert to... (kf_calloc::impl_call_pre): ...this. (kf_connect::matches_call_types_p): Rewrite check to use call_details::arg_is_pointer_p. (region_model::impl_call_error): Convert to... (class kf_error): ...this, and... (kf_error::impl_call_pre): ...this. (class kf_fgets): New, adding checks that args 0 and 2 are pointers. (region_model::impl_call_fgets): Convert to... (kf_fgets::impl_call_pre): ...this. (class kf_fread): New, adding checks on the argument types. (region_model::impl_call_fread): Convert to... (kf_fread::impl_call_pre): ...this. (class kf_free): New, adding check that the argument is a pointer. (region_model::impl_call_free): Convert to... (kf_free::impl_call_post): ...this. (class kf_getchar): New. (class kf_malloc): New, adding check that the argument is a size_t. (region_model::impl_call_malloc): Convert to... (kf_malloc::impl_call_pre): ...this. (class kf_memcpy): New, adding checks on arguments. (region_model::impl_call_memcpy): Convert to... (kf_memcpy::impl_call_pre): ...this. (class kf_memset): New. (region_model::impl_call_memset): Convert to... (kf_memset::impl_call_pre): ...this. (kf_pipe::matches_call_types_p): Rewrite check to use call_details::arg_is_pointer_p. (kf_putenv::matches_call_types_p): Likewise. (class kf_realloc): New, adding checks on the argument types. (region_model::impl_call_realloc): Convert to... (kf_realloc::impl_call_post): ...this. (class kf_strchr): New. (region_model::impl_call_strchr): Convert to... (kf_strchr::impl_call_post): ...this. (class kf_stack_restore): New. (class kf_stack_save): New. (class kf_stdio_output_fn): New. (class kf_strcpy): New, (region_model::impl_call_strcpy): Convert to... (kf_strcpy::impl_call_pre): ...this. (class kf_strlen): New. (region_model::impl_call_strlen): Convert to... (kf_strlen::impl_call_pre): ...this. (class kf_ubsan_bounds): New. (region_model::impl_deallocation_call): Reimplement to avoid call to impl_call_free. (register_known_functions): Add handlers for IFN_BUILTIN_EXPECT and IFN_UBSAN_BOUNDS. Add handlers for BUILT_IN_ALLOCA, BUILT_IN_ALLOCA_WITH_ALIGN, BUILT_IN_CALLOC, BUILT_IN_EXPECT, BUILT_IN_EXPECT_WITH_PROBABILITY, BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_FPUTC, BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_FPUTS, BUILT_IN_FPUTS_UNLOCKED, BUILT_IN_FREE, BUILT_IN_FWRITE, BUILT_IN_FWRITE_UNLOCKED, BUILT_IN_MALLOC, BUILT_IN_MEMCPY, BUILT_IN_MEMCPY_CHK, BUILT_IN_MEMSET, BUILT_IN_MEMSET_CHK, 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_REALLOC, BUILT_IN_STACK_RESTORE, BUILT_IN_STACK_SAVE, BUILT_IN_STRCHR, BUILT_IN_STRCPY, BUILT_IN_STRCPY_CHK, BUILT_IN_STRLEN, BUILT_IN_VFPRINTF, and BUILT_IN_VPRINTF. Call register_varargs_builtins. Add handlers for "getchar", "memset", "fgets", "fgets_unlocked", "fread", "error", and "error_at_line". * region-model.cc (region_model::on_stmt_pre): Drop "out_terminate_path" param. (region_model::get_known_function): Reimplement by calling known_function_manager::get_match, passing new "cd" param. Add overload taking enum internal_fn. (region_model::on_call_pre): Drop "out_terminate_path" param. Remove special-case handling of internal fns IFN_BUILTIN_EXPECT, IFN_UBSAN_BOUNDS, and IFN_VA_ARG, of built-in fns BUILT_IN_ALLOCA, BUILT_IN_ALLOCA_WITH_ALIGN, BUILT_IN_CALLOC, BUILT_IN_EXPECT, BUILT_IN_EXPECT_WITH_PROBABILITY, BUILT_IN_FREE, BUILT_IN_MALLOC, BUILT_IN_MEMCPY, BUILT_IN_MEMCPY_CHK, BUILT_IN_MEMSET, BUILT_IN_MEMSET_CHK, BUILT_IN_REALLOC, BUILT_IN_STRCHR, BUILT_IN_STRCPY, BUILT_IN_STRCPY_CHK, BUILT_IN_STRLEN, BUILT_IN_STACK_SAVE, BUILT_IN_STACK_RESTORE, BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_PUTC, BUILT_IN_PUTC_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_PUTCHAR, BUILT_IN_PUTCHAR_UNLOCKED, BUILT_IN_PUTS, BUILT_IN_PUTS_UNLOCKED, BUILT_IN_VFPRINTF, BUILT_IN_VPRINTF, BUILT_IN_VA_START, and BUILT_IN_VA_COPY, and of named functions "malloc", "calloc", "alloca", "realloc", "error", "error_at_line", "fgets", "fgets_unlocked", "fread", "getchar", "memset", "strchr", and "strlen". Replace all this special-casing with calls to get_known_function for internal fns and for fn decls. (region_model::on_call_post): Remove special-casing handling for "free" and "strchr", and for BUILT_IN_REALLOC, BUILT_IN_STRCHR, and BUILT_IN_VA_END. Replace by consolidating on usage of get_known_function. * region-model.h (call_details::arg_is_size_p): New. (region_model::on_stmt_pre): Drop "out_terminate_path" param. (region_model::on_call_pre): Likewise. (region_model::impl_call_alloca): Delete. (region_model::impl_call_builtin_expect): Delete. (region_model::impl_call_calloc): Delete. (region_model::impl_call_error): Delete. (region_model::impl_call_fgets): Delete. (region_model::impl_call_fread): Delete. (region_model::impl_call_free): Delete. (region_model::impl_call_malloc): Delete. (region_model::impl_call_memcpy): Delete. (region_model::impl_call_memset): Delete. (region_model::impl_call_realloc): Delete. (region_model::impl_call_strchr): Delete. (region_model::impl_call_strcpy): Delete. (region_model::impl_call_strlen): Delete. (region_model::impl_call_va_start): Delete. (region_model::impl_call_va_copy): Delete. (region_model::impl_call_va_arg): Delete. (region_model::impl_call_va_end): Delete. (region_model::check_region_for_write): Public. (region_model::get_known_function): Add "cd" param. Add overloaded decl taking enum internal_fn. * sm-malloc.cc: Update comments. * varargs.cc (class kf_va_start): New. (region_model::impl_call_va_start): Convert to... (kf_va_start::impl_call_pre): ...this. (class kf_va_copy): New. (region_model::impl_call_va_copy): Convert to... (kf_va_copy::impl_call_pre): ...this. (class kf_va_arg): New. (region_model::impl_call_va_arg): Convert to... (kf_va_arg::impl_call_pre): ...this. (class kf_va_end): New. (region_model::impl_call_va_end): Delete. (register_varargs_builtins): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-22Daily bump.GCC Administrator1-0/+24
2022-11-21analyzer: fix ICE on 'bind' that returns a struct [PR107788]David Malcolm1-0/+4
gcc/analyzer/ChangeLog: PR analyzer/107788 * region-model.cc (region_model::update_for_int_cst_return): Require that the return type be an integer type. (region_model::update_for_nonzero_return): Likewise. gcc/testsuite/ChangeLog: PR analyzer/107788 * g++.dg/analyzer/fd-bind-pr107783.C: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-21analyzer: fix ICE on 'bind' with non-pointer arg [P107783]David Malcolm2-2/+8
gcc/analyzer/ChangeLog: PR analyzer/107783 * region-model-impl-calls.cc (kf_accept::matches_call_types_p): Require that args 1 and 2 be pointers. (kf_bind::matches_call_types_p): Require that arg 1 be a pointer. * region-model.h (call_details::arg_is_pointer_p): New gcc/testsuite/ChangeLog: PR analyzer/107783 * gcc.dg/analyzer/fd-bind-pr107783.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-21analyzer: fix ICE on writes to errno [PR107777]David Malcolm2-0/+4
gcc/analyzer/ChangeLog: PR analyzer/107777 * call-summary.cc (call_summary_replay::convert_region_from_summary_1): Handle RK_THREAD_LOCAL and RK_ERRNO in switch. * region-model.cc (region_model::get_representative_path_var_1): Likewise. gcc/testsuite/ChangeLog: PR analyzer/107777 * gcc.dg/analyzer/call-summaries-errno.c: New test. * gcc.dg/analyzer/errno-pr107777.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-21changelog: Fix extra space after tab.Martin Liska1-3/+3
2022-11-21Daily bump.GCC Administrator1-0/+89
2022-11-18analyzer: fix feasibility false +ve on jumps through function ptrs [PR107582]David Malcolm1-4/+10
PR analyzer/107582 reports a false +ve from -Wanalyzer-use-of-uninitialized-value where the analyzer's feasibility checker erroneously decides that point (B) in the code below is reachable, with "x" being uninitialized there: pthread_cleanup_push(func, NULL); while (ret != ETIMEDOUT) ret = rand() % 1000; /* (A): after the while loop */ if (ret != ETIMEDOUT) x = &z; pthread_cleanup_pop(1); if (ret == ETIMEDOUT) return 0; /* (B): after not bailing out */ due to these contradictionary conditions somehow both holding: * (ret == ETIMEDOUT), at (A) (skipping the initialization of x), and * (ret != ETIMEDOUT), at (B) The root cause is that after the while loop, state merger puts ret in the exploded graph in an UNKNOWN state, and saves the diagnostic at (B). Later, as we explore the feasibilty of reaching the enode for (B), dynamic_call_info_t::update_model is called to push/pop the frames for handling the call to "func" in pthread_cleanup_pop. The "ret" at these nodes in the feasible_graph has a conjured_svalue for "ret", and a constraint on it being either == *or* != ETIMEDOUT. However dynamic_call_info_t::update_model blithely clobbers the model with a copy from the exploded_graph, in which "ret" is UNKNOWN. This patch fixes dynamic_call_info_t::update_model so that it simulates pushing/popping a frame on the model we're working with, preserving knowledge of the constraint on "ret", and enabling the analyzer to "know" that the bail-out must happen. Doing so fixes the false positive. gcc/analyzer/ChangeLog: PR analyzer/107582 * engine.cc (dynamic_call_info_t::update_model): Update the model by pushing or pop a frame, rather than by clobbering it with the model from the exploded_node's state. gcc/testsuite/ChangeLog: PR analyzer/107582 * gcc.dg/analyzer/feasibility-4.c: New test. * gcc.dg/analyzer/feasibility-pr107582-1.c: New test. * gcc.dg/analyzer/feasibility-pr107582-2.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-18analyzer: move more impl_* to known_functionDavid Malcolm6-335/+450
Fix a missing check that the argument to __analyzer_dump_capacity must be a pointer type (which would otherwise lead to an ICE). Do so by using the known_function_manager rather than by doing lots of string matching. Do the same for many other functions. Doing so moves the type-checking closer to the logic that makes use of it, by putting them in the same class, rather than splitting them up between two source files (and sometimes three, e.g. for "pipe"). I hope this reduces the number of missing checks. gcc/analyzer/ChangeLog: * analyzer.cc (is_pipe_call_p): Delete. * analyzer.h (is_pipe_call_p): Delete. * region-model-impl-calls.cc (call_details::get_location): New. (class kf_analyzer_break): New, adapted from region_model::on_stmt_pre. (region_model::impl_call_analyzer_describe): Convert to... (class kf_analyzer_describe): ...this. (region_model::impl_call_analyzer_dump_capacity): Convert to... (class kf_analyzer_dump_capacity): ...this. (region_model::impl_call_analyzer_dump_escaped): Convert to... (class kf_analyzer_dump_escaped): ...this. (class kf_analyzer_dump_exploded_nodes): New. (region_model::impl_call_analyzer_dump_named_constant): Convert to... (class kf_analyzer_dump_named_constant): ...this. (class dump_path_diagnostic): Move here from region-model.cc. (class kf_analyzer_dump_path) New, adapted from region_model::on_stmt_pre. (class kf_analyzer_dump_region_model): Likewise. (region_model::impl_call_analyzer_eval): Convert to... (class kf_analyzer_eval): ...this. (region_model::impl_call_analyzer_get_unknown_ptr): Convert to... (class kf_analyzer_get_unknown_ptr): ...this. (class known_function_accept): Rename to... (class kf_accept): ...this. (class known_function_bind): Rename to... (class kf_bind): ...this. (class known_function_connect): Rename to... (class kf_connect): ...this. (region_model::impl_call_errno_location): Convert to... (class kf_errno_location): ...this. (class known_function_listen): Rename to... (class kf_listen): ...this. (region_model::impl_call_pipe): Convert to... (class kf_pipe): ...this. (region_model::impl_call_putenv): Convert to... (class kf_putenv): ...this. (region_model::impl_call_operator_new): Convert to... (class kf_operator_new): ...this. (region_model::impl_call_operator_delete): Convert to... (class kf_operator_delete): ...this. (class known_function_socket): Rename to... (class kf_socket): ...this. (register_known_functions): Rename param to KFM. Break out existing known functions into a "POSIX" section, and add "pipe", "pipe2", and "putenv". Add debugging functions "__analyzer_break", "__analyzer_describe", "__analyzer_dump_capacity", "__analyzer_dump_escaped", "__analyzer_dump_exploded_nodes", "__analyzer_dump_named_constant", "__analyzer_dump_path", "__analyzer_dump_region_model", "__analyzer_eval", "__analyzer_get_unknown_ptr". Add C++ support functions "operator new", "operator new []", "operator delete", and "operator delete []". * region-model.cc (class dump_path_diagnostic): Move to region-model-impl-calls.cc. (region_model::on_stmt_pre): Eliminate special-casing of "__analyzer_describe", "__analyzer_dump_capacity", "__analyzer_dump_escaped", "__analyzer_dump_named_constant", "__analyzer_dump_path", "__analyzer_dump_region_model", "__analyzer_eval", "__analyzer_break", "__analyzer_dump_exploded_nodes", "__analyzer_get_unknown_ptr", "__errno_location", "pipe", "pipe2", "putenv", "operator new", "operator new []", "operator delete", "operator delete []" "pipe" and "pipe2", handling them instead via the known_functions mechanism. * region-model.h (call_details::get_location): New decl. (region_model::impl_call_analyzer_describe): Delete decl. (region_model::impl_call_analyzer_dump_capacity): Delete decl. (region_model::impl_call_analyzer_dump_escaped): Delete decl. (region_model::impl_call_analyzer_dump_named_constant): Delete decl. (region_model::impl_call_analyzer_eval): Delete decl. (region_model::impl_call_analyzer_get_unknown_ptr): Delete decl. (region_model::impl_call_errno_location): Delete decl. (region_model::impl_call_pipe): Delete decl. (region_model::impl_call_putenv): Delete decl. (region_model::impl_call_operator_new): Delete decl. (region_model::impl_call_operator_delete): Delete decl. * sm-fd.cc: Update comments. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-debugging-fns-1.c: New test. * gcc.dg/analyzer/attr-const-3.c: Increase the "analyzer-max-svalue-depth" from 0 to 4 to ensure that "__analyzer_eval" is recognized. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-17Daily bump.GCC Administrator1-0/+55
2022-11-16analyzer: log the stashing of named constants [PR107711]David Malcolm3-23/+71
PR analyzer/107711 seems to be a bug in how named constants are looked up by the analyzer in the C frontend. To help debug this, this patch extends -fdump-analyzer and -fdump-analyzer-stderr so that they dump this part of the analyzer's startup. gcc/analyzer/ChangeLog: PR analyzer/107711 * analyzer-language.cc: Include "diagnostic.h". (maybe_stash_named_constant): Add logger param and use it to log the name being looked up, and the result. (stash_named_constants): New, splitting out from... (on_finish_translation_unit): ...this function. Call get_or_create_logfile and use the result to create a logger instance, passing it to stash_named_constants. * analyzer.h (get_or_create_any_logfile): New decl. * engine.cc (dump_fout, owns_dump_fout): New globals, split out from run_checkers. (get_or_create_any_logfile): New function, split out from... (run_checkers): ...here, so that the logfile can be opened by on_finish_translation_unit. Clear the globals when closing the dump file. gcc/testsuite/ChangeLog: PR analyzer/107711 * gcc.dg/analyzer/fdump-analyzer-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-16analyzer: use known_function to simplify region_model::on_call_{pre,post}David Malcolm6-99/+139
Replace lots of repeated checks against strings with a hash_map lookup. Add some missing type-checking for handling known functions (e.g. checks for pointer types). gcc/analyzer/ChangeLog: * analyzer.h (known_function::matches_call_types_p): New vfunc. (known_function::impl_call_pre): Provide base implementation. (known_function::impl_call_post): New vfunc. (register_known_functions): New. * engine.cc (impl_run_checkers): Call register_known_functions. * region-model-impl-calls.cc (region_model::impl_call_accept): Convert to... (class known_function_accept): ...this. (region_model::impl_call_bind): Convert to... (class known_function_bind): ...this. (region_model::impl_call_connect): Convert to... (class known_function_connect): ...this. (region_model::impl_call_listen): Convert to... (class known_function_listen): ...this. (region_model::impl_call_socket): Convert to... (class known_function_socket): ...this. (register_known_functions): New. * region-model.cc (region_model::on_call_pre): Remove special case for "bind" in favor of the known_function-handling dispatch. Add call to known_function::matches_call_types_p to latter. (region_model::on_call_post): Remove special cases for "accept", "bind", "connect", "listen", and "socket" in favor of dispatch to known_function::impl_call_post. * region-model.h (region_model::impl_call_accept): Delete decl. (region_model::impl_call_bind): Delete decl. (region_model::impl_call_connect): Delete decl. (region_model::impl_call_listen): Delete decl. (region_model::impl_call_socket): Delete decl. * sm-fd.cc: Update comments. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c (copy_across_boundary_fn::matches_call_types_p): New. * gcc.dg/plugin/analyzer_known_fns_plugin.c (known_function_returns_42::matches_call_types_p): New. (known_function_attempt_to_copy::matches_call_types_p): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-16analyzer: split out checker-path.cc into a new checker-event.ccDavid Malcolm2-1149/+1214
gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Add analyzer/checker-event.o. gcc/analyzer/ChangeLog: * checker-event.cc: New file, split out from... * checker-path.cc: ...this file. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-16Daily bump.GCC Administrator1-0/+105
2022-11-15analyzer: add warnings relating to sockets [PR106140]David Malcolm9-58/+1433
This patch generalizes the analyzer's file descriptor state machine so that it tracks the states of sockets. It adds two new warnings relating to misuses of socket APIs: * -Wanalyzer-fd-phase-mismatch (e.g. calling 'accept' on a socket before calling 'listen' on it) * -Wanalyzer-fd-type-mismatch (e.g. using a stream socket operation on a datagram socket) gcc/analyzer/ChangeLog: PR analyzer/106140 * analyzer-language.cc (on_finish_translation_unit): Stash named constants "SOCK_STREAM" and "SOCK_DGRAM". * analyzer.opt (Wanalyzer-fd-phase-mismatch): New. (Wanalyzer-fd-type-mismatch): New. * engine.cc (impl_region_model_context::get_state_map_by_name): Add "out_sm_context" param. Allow out_sm_idx to be NULL. * exploded-graph.h (impl_region_model_context::get_state_map_by_name): Add "out_sm_context" param. * region-model-impl-calls.cc (region_model::impl_call_accept): New. (region_model::impl_call_bind): New. (region_model::impl_call_connect): New. (region_model::impl_call_listen): New. (region_model::impl_call_socket): New. * region-model.cc (region_model::on_call_pre): Special-case "bind". (region_model::on_call_post): Special-case "accept", "bind", "connect", "listen", and "socket". * region-model.h (region_model::impl_call_accept): New decl. (region_model::impl_call_bind): New decl. (region_model::impl_call_connect): New decl. (region_model::impl_call_listen): New decl. (region_model::impl_call_socket): New decl. (region_model::on_socket): New decl. (region_model::on_bind): New decl. (region_model::on_listen): New decl. (region_model::on_accept): New decl. (region_model::on_connect): New decl. (region_model::add_constraint): Make public. (region_model::check_for_poison): Make public. (region_model_context::get_state_map_by_name): Add out_sm_context param. (region_model_context::get_fd_map): Likewise. (region_model_context::get_malloc_map): Likewise. (region_model_context::get_taint_map): Likewise. (noop_region_model_context::get_state_map_by_name): Likewise. (region_model_context_decorator::get_state_map_by_name): Likewise. * sm-fd.cc: Include "analyzer/supergraph.h" and "analyzer/analyzer-language.h". (enum expected_phase): New enum. (fd_state_machine::m_new_datagram_socket): New. (fd_state_machine::m_new_stream_socket): New. (fd_state_machine::m_new_unknown_socket): New. (fd_state_machine::m_bound_datagram_socket): New. (fd_state_machine::m_bound_stream_socket): New. (fd_state_machine::m_bound_unknown_socket): New. (fd_state_machine::m_listening_stream_socket): New. (fd_state_machine::m_m_connected_stream_socket): New. (fd_state_machine::m_SOCK_STREAM): New. (fd_state_machine::m_SOCK_DGRAM): New. (fd_diagnostic::describe_state_change): Handle socket states. (fd_diagnostic::get_meaning_for_state_change): Likewise. (class fd_phase_mismatch): New. (enum expected_type): New enum. (class fd_type_mismatch): New. (fd_state_machine::fd_state_machine): Initialize new states and stashed named constants. (fd_state_machine::is_socket_fd_p): New. (fd_state_machine::is_datagram_socket_fd_p): New. (fd_state_machine::is_stream_socket_fd_p): New. (fd_state_machine::on_close): Handle the socket states. (fd_state_machine::check_for_open_fd): Complain about fncalls on sockets in the wrong phase. Support socket FDs. (add_constraint_ge_zero): New. (fd_state_machine::get_state_for_socket_type): New. (fd_state_machine::on_socket): New. (fd_state_machine::check_for_socket_fd): New. (fd_state_machine::check_for_new_socket_fd): New. (fd_state_machine::on_bind): New. (fd_state_machine::on_listen): New. (fd_state_machine::on_accept): New. (fd_state_machine::on_connect): New. (fd_state_machine::can_purge_p): Don't purge socket values. (get_fd_state): New. (region_model::mark_as_valid_fd): Use get_fd_state. (region_model::on_socket): New. (region_model::on_bind): New. (region_model::on_listen): New. (region_model::on_accept): New. (region_model::on_connect): New. * sm-fd.dot: Update to reflect sm-fd.cc changes. gcc/ChangeLog: PR analyzer/106140 * doc/invoke.texi (Static Analyzer Options): Add -Wanalyzer-fd-phase-mismatch and -Wanalyzer-fd-type-mismatch. Add "socket", "bind", "listen", "accept", and "connect" to the list of functions known to the analyzer. gcc/testsuite/ChangeLog: PR analyzer/106140 * gcc.dg/analyzer/fd-accept.c: New test. * gcc.dg/analyzer/fd-bind.c: New test. * gcc.dg/analyzer/fd-connect.c: New test. * gcc.dg/analyzer/fd-datagram-socket.c: New test. * gcc.dg/analyzer/fd-glibc-byte-stream-connection-server.c: New test. * gcc.dg/analyzer/fd-glibc-byte-stream-socket.c: New test. * gcc.dg/analyzer/fd-glibc-datagram-client.c: New test. * gcc.dg/analyzer/fd-glibc-datagram-socket.c: New test. * gcc.dg/analyzer/fd-glibc-make_named_socket.h: New test. * gcc.dg/analyzer/fd-listen.c: New test. * gcc.dg/analyzer/fd-manpage-getaddrinfo-client.c: New test. * gcc.dg/analyzer/fd-mappage-getaddrinfo-server.c: New test. * gcc.dg/analyzer/fd-socket-meaning.c: New test. * gcc.dg/analyzer/fd-socket-misuse.c: New test. * gcc.dg/analyzer/fd-stream-socket-active-open.c: New test. * gcc.dg/analyzer/fd-stream-socket-passive-open.c: New test. * gcc.dg/analyzer/fd-stream-socket.c: New test. * gcc.dg/analyzer/fd-symbolic-socket.c: New test. * gcc.dg/analyzer/pr104369-1.c: Add -Wno-analyzer-too-complex and -Wno-analyzer-fd-leak to options. * gcc.dg/analyzer/pr104369-2.c: Add -Wno-analyzer-fd-leak to options. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-15c, analyzer: support named constants in analyzer [PR106302]David Malcolm8-10/+216
The analyzer's file-descriptor state machine tracks the access mode of opened files, so that it can emit -Wanalyzer-fd-access-mode-mismatch. To do this, its symbolic execution needs to "know" the values of the constants "O_RDONLY", "O_WRONLY", and "O_ACCMODE". Currently analyzer/sm-fd.cc simply uses these values directly from the build-time header files, but these are the values on the host, not those from the target, which could be different (PR analyzer/106302). In an earlier discussion of this issue: https://gcc.gnu.org/pipermail/gcc/2022-June/238954.html we talked about adding a target hook for this. However, I've also been experimenting with extending the fd state machine to track sockets (PR analyzer/106140). For this, it's useful to "know" the values of the constants "SOCK_STREAM" and "SOCK_DGRAM". Unfortunately, these seem to have many arbitrary differences from target to target. For example: Linux/glibc general has SOCK_STREAM == 1, SOCK_DGRAM == 2, as does AIX, but annoyingly, e.g. Linux on MIPS has them the other way around. It seems to me that as the analyzer grows more ambitious modeling of the behavior of APIs (perhaps via plugins) it's more likely that the analyzer will need to know the values of named constants, which might not even exist on the host. For example, at LPC it was suggested to me that -fanalyzer could check rules about memory management inside the Linux kernel (probably via a plugin), but doing so involves a bunch of GFP_* flags (see PR 107472). So rather than trying to capture all this knowledge in a target hook, this patch attempts to get at named constant values from the user's source code. The patch adds an interface for frontends to call into the analyzer as the translation unit finishes. The analyzer can then call back into the frontend to ask about the values of the named constants it cares about whilst the frontend's data structures are still around. The patch implements this for the C frontend, which looks up the names by looking for named CONST_DECLs (which handles enum values). Failing that, it attempts to look up the values of macros but only the simplest cases are supported (a non-traditional macro with a single CPP_NUMBER token). It does this by building a buffer containing the macro definition and rerunning a lexer on it. The analyzer gracefully handles the cases where named values aren't found (such as anything more complicated than described above). The patch ports the analyzer to use this mechanism for "O_RDONLY", "O_WRONLY", and "O_ACCMODE". I have successfully tested my socket patch to also use this for "SOCK_STREAM" and "SOCK_DGRAM", so the technique seems to work. gcc/ChangeLog: PR analyzer/106302 * Makefile.in (ANALYZER_OBJS): Add analyzer/analyzer-language.o. (GTFILES): Add analyzer/analyzer-language.cc. * doc/analyzer.texi: Document __analyzer_dump_named_constant. gcc/analyzer/ChangeLog: PR analyzer/106302 * analyzer-language.cc: New file. * analyzer-language.h: New file. * analyzer.h (get_stashed_constant_by_name): New decl. (log_stashed_constants): New decl. * engine.cc (impl_run_checkers): Call log_stashed_constants. * region-model-impl-calls.cc (region_model::impl_call_analyzer_dump_named_constant): New. * region-model.cc (region_model::on_stmt_pre): Handle __analyzer_dump_named_constant. * region-model.h (region_model::impl_call_analyzer_dump_named_constant): New decl. * sm-fd.cc (fd_state_machine::m_O_ACCMODE): New. (fd_state_machine::m_O_RDONLY): New. (fd_state_machine::m_O_WRONLY): New. (fd_state_machine::fd_state_machine): Initialize the new fields. (fd_state_machine::get_access_mode_from_flag): Use the new fields, rather than using the host values. gcc/c/ChangeLog: PR analyzer/106302 * c-parser.cc: Include "analyzer/analyzer-language.h" and "toplev.h". (class ana::c_translation_unit): New. (c_parser_translation_unit): Call ana::on_finish_translation_unit. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_named_constant): New decl. * gcc.dg/analyzer/fd-4.c (void): Likewise. (O_ACCMODE): Define. * gcc.dg/analyzer/fd-access-mode-enum.c: New test, based on . * gcc.dg/analyzer/fd-5.c: ...this. Rename to... * gcc.dg/analyzer/fd-access-mode-macros.c: ...this. (O_ACCMODE): Define. * gcc.dg/analyzer/fd-access-mode-target-headers.c: New test, also based on fd-5.c. (test_sm_fd_constants): New. * gcc.dg/analyzer/fd-dup-1.c (O_ACCMODE): Define. * gcc.dg/analyzer/named-constants-via-enum.c: New test. * gcc.dg/analyzer/named-constants-via-enum-and-macro.c: New test. * gcc.dg/analyzer/named-constants-via-macros-2.c: New test. * gcc.dg/analyzer/named-constants-via-macros.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-14Daily bump.GCC Administrator1-0/+26
2022-11-13analyzer: new warning: -Wanalyzer-tainted-assertion [PR106235]David Malcolm6-20/+181
This patch adds a new -Wanalyzer-tainted-assertion warning to -fanalyzer's "taint" mode (which also requires -fanalyzer-checker=taint). It complains about attacker-controlled values being used in assertions, or in any expression affecting control flow that guards a "noreturn" function. As noted in the docs part of the patch, in such cases: - when assertion-checking is enabled: an attacker could trigger a denial of service by injecting an assertion failure - when assertion-checking is disabled, such as by defining NDEBUG, an attacker could inject data that subverts the process, since it presumably violates a precondition that is being assumed by the code. For example, given: #include <assert.h> int __attribute__((tainted_args)) test_tainted_assert (int n) { assert (n > 0); return n * n; } compiling with -fanalyzer -fanalyzer-checker=taint gives: t.c: In function 'test_tainted_assert': t.c:6:3: warning: use of attacked-controlled value in condition for assertion [CWE-617] [-Wanalyzer-tainted-assertion] 6 | assert (n > 0); | ^~~~~~ 'test_tainted_assert': event 1 | | 4 | test_tainted_assert (int n) | | ^~~~~~~~~~~~~~~~~~~ | | | | | (1) function 'test_tainted_assert' marked with '__attribute__((tainted_args))' | +--> 'test_tainted_assert': event 2 | | 4 | test_tainted_assert (int n) | | ^~~~~~~~~~~~~~~~~~~ | | | | | (2) entry to 'test_tainted_assert' | 'test_tainted_assert': events 3-6 | |/usr/include/assert.h:106:10: | 106 | if (expr) \ | | ^ | | | | | (3) use of attacker-controlled value for control flow | | (4) following 'false' branch (when 'n <= 0')... |...... | 109 | __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \ | | ~~~~~~~~~~~~~ | | | | | (5) ...to here | | (6) treating '__assert_fail' as an assertion failure handler due to '__attribute__((__noreturn__))' | The testcases have various examples for BUG and BUG_ON from the Linux kernel; there, the diagnostic treats "panic" as an assertion failure handler, due to '__attribute__((__noreturn__))'. gcc/analyzer/ChangeLog: PR analyzer/106235 * analyzer.opt (Wanalyzer-tainted-assertion): New. * checker-path.cc (checker_path::fixup_locations): Pass false to pending_diagnostic::fixup_location. * diagnostic-manager.cc (get_emission_location): Pass true to pending_diagnostic::fixup_location. * pending-diagnostic.cc (pending_diagnostic::fixup_location): Add bool param. * pending-diagnostic.h (pending_diagnostic::fixup_location): Add bool param to decl. * sm-taint.cc (taint_state_machine::m_tainted_control_flow): New. (taint_diagnostic::describe_state_change): Drop "final". (class tainted_assertion): New. (taint_state_machine::taint_state_machine): Initialize m_tainted_control_flow. (taint_state_machine::alt_get_inherited_state): Support comparisons being tainted, based on their arguments. (is_assertion_failure_handler_p): New. (taint_state_machine::on_stmt): Complain about calls to assertion failure handlers guarded by an attacker-controller conditional. Detect attacker-controlled gcond conditionals and gswitch index values. (taint_state_machine::check_control_flow_arg_for_taint): New. gcc/ChangeLog: PR analyzer/106235 * doc/gcc/gcc-command-options/option-summary.rst: Add -Wno-analyzer-tainted-assertion. * doc/gcc/gcc-command-options/options-that-control-static-analysis.rst: Add -Wno-analyzer-tainted-assertion. gcc/testsuite/ChangeLog: PR analyzer/106235 * gcc.dg/analyzer/taint-assert-BUG_ON.c: New test. * gcc.dg/analyzer/taint-assert-macro-expansion.c: New test. * gcc.dg/analyzer/taint-assert.c: New test. * gcc.dg/analyzer/taint-assert-system-header.c: New test. * gcc.dg/analyzer/test-assert.h: New header. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::fixup_location): Add bool param. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-12Daily bump.GCC Administrator1-0/+49