diff options
author | David Malcolm <dmalcolm@redhat.com> | 2022-05-16 15:32:11 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2022-05-16 15:34:09 -0400 |
commit | 2402dc6b982c4dacac2360830f0edc123c588110 (patch) | |
tree | 95f38ecf7b3a91c1c413e2b782f1a54eb3b4b894 /gcc/doc | |
parent | 5eb9927aae076200bb7ba3f22c33b0a7c97c5643 (diff) | |
download | gcc-2402dc6b982c4dacac2360830f0edc123c588110.zip gcc-2402dc6b982c4dacac2360830f0edc123c588110.tar.gz gcc-2402dc6b982c4dacac2360830f0edc123c588110.tar.bz2 |
analyzer: implement four new warnings for <stdarg.h> misuses [PR105103]
This patch adds support to the analyzer for checking usage of <stdarg.h>,
with four new warnings.
It adds:
(a) a state-machine for tracking "started" and "ended" states on va_list
instances, implementing two new warnings:
-Wanalyzer-va-list-leak
for complaining about missing va_end after a va_start or va_copy
-Wanalyzer-va-list-use-after-va-end:
for complaining about va_arg or va_copy used on a va_list that's had
va_end called on it
(b) interprocedural tracking of variadic parameters, tracking symbolic
values, implementing two new warnings:
-Wanalyzer-va-arg-type-mismatch
for type-checking va_arg usage against the types of the parameters
that were actually passed to the variadic call
-Wanalyzer-va-list-exhausted
for complaining if va_arg is used too many times on a va_list
Here's an LTO example of a type mismatch in a variadic call that
straddles two source files:
stdarg-lto-1-a.c: In function 'called_by_test_type_mismatch_1':
stdarg-lto-1-a.c:19:7: warning: 'va_arg' expected 'const char *' but
received 'int' for variadic argument 1 of 'ap' [-Wanalyzer-va-arg-type-mismatch]
19 | str = va_arg (ap, const char *);
| ^
'test_type_mismatch_1': events 1-2
|
|stdarg-lto-1-b.c:3:6:
| 3 | void test_type_mismatch_1 (void)
| | ^
| | |
| | (1) entry to 'test_type_mismatch_1'
| 4 | {
| 5 | called_by_test_type_mismatch_1 (42, 1066);
| | ~
| | |
| | (2) calling 'called_by_test_type_mismatch_1' from 'test_type_mismatch_1' with 1 variadic argument
|
+--> 'called_by_test_type_mismatch_1': events 3-4
|
|stdarg-lto-1-a.c:12:1:
| 12 | called_by_test_type_mismatch_1 (int placeholder, ...)
| | ^
| | |
| | (3) entry to 'called_by_test_type_mismatch_1'
|......
| 19 | str = va_arg (ap, const char *);
| | ~
| | |
| | (4) 'va_arg' expected 'const char *' but received 'int' for variadic argument 1 of 'ap'
|
gcc/ChangeLog:
PR analyzer/105103
* Makefile.in (ANALYZER_OBJS): Add analyzer/varargs.o.
* doc/invoke.texi: Add -Wanalyzer-va-arg-type-mismatch,
-Wanalyzer-va-list-exhausted, -Wanalyzer-va-list-leak, and
-Wanalyzer-va-list-use-after-va-end.
gcc/analyzer/ChangeLog:
PR analyzer/105103
* analyzer.cc (make_label_text_n): New.
* analyzer.h (class var_arg_region): New forward decl.
(make_label_text_n): New decl.
* analyzer.opt (Wanalyzer-va-arg-type-mismatch): New option.
(Wanalyzer-va-list-exhausted): New option.
(Wanalyzer-va-list-leak): New option.
(Wanalyzer-va-list-use-after-va-end): New option.
* checker-path.cc (call_event::get_desc): Split out decl access
into..
(call_event::get_caller_fndecl): ...this new function and...
(call_event::get_callee_fndecl): ...this new function.
* checker-path.h (call_event::get_desc): Drop "FINAL".
(call_event::get_caller_fndecl): New decl.
(call_event::get_callee_fndecl): New decl.
(class call_event): Make fields protected.
* diagnostic-manager.cc (null_assignment_sm_context::warn): New
overload.
(null_assignment_sm_context::get_new_program_state): New.
(diagnostic_manager::add_events_for_superedge): Move case
SUPEREDGE_CALL to a new pending_diagnostic::add_call_event vfunc.
* engine.cc (impl_sm_context::warn): Implement new override.
(impl_sm_context::get_new_program_state): New.
* pending-diagnostic.cc: Include "analyzer/diagnostic-manager.h",
"cpplib.h", "digraph.h", "ordered-hash-map.h", "cfg.h",
"basic-block.h", "gimple.h", "gimple-iterator.h", "cgraph.h"
"analyzer/supergraph.h", "analyzer/program-state.h",
"alloc-pool.h", "fibonacci_heap.h", "shortest-paths.h",
"sbitmap.h", "analyzer/exploded-graph.h", "diagnostic-path.h",
and "analyzer/checker-path.h".
(ht_ident_eq): New.
(fixup_location_in_macro_p): New.
(pending_diagnostic::fixup_location): New.
(pending_diagnostic::add_call_event): New.
* pending-diagnostic.h (pending_diagnostic::fixup_location): Drop
no-op inline implementation in favor of the more complex
implementation above.
(pending_diagnostic::add_call_event): New vfunc.
* region-model-impl-calls.cc: Include "analyzer/sm.h",
"diagnostic-path.h", and "analyzer/pending-diagnostic.h".
* region-model-manager.cc
(region_model_manager::get_var_arg_region): New.
(region_model_manager::log_stats): Log m_var_arg_regions.
* region-model.cc (region_model::on_call_pre): Handle IFN_VA_ARG,
BUILT_IN_VA_START, and BUILT_IN_VA_COPY.
(region_model::on_call_post): Handle BUILT_IN_VA_END.
(region_model::get_representative_path_var_1): Handle RK_VAR_ARG.
(region_model::push_frame): Push variadic arguments.
* region-model.h (region_model_manager::get_var_arg_region): New
decl.
(region_model_manager::m_var_arg_regions): New field.
(region_model::impl_call_va_start): New decl.
(region_model::impl_call_va_copy): New decl.
(region_model::impl_call_va_arg): New decl.
(region_model::impl_call_va_end): New decl.
* region.cc (alloca_region::dump_to_pp): Dump the id.
(var_arg_region::dump_to_pp): New.
(var_arg_region::get_frame_region): New.
* region.h (enum region_kind): Add RK_VAR_ARG.
(region::dyn_cast_var_arg_region): New.
(class var_arg_region): New.
(is_a_helper <const var_arg_region *>::test): New.
(struct default_hash_traits<var_arg_region::key_t>): New.
* sm.cc (make_checkers): Call make_va_list_state_machine.
* sm.h (sm_context::warn): New vfunc.
(sm_context::get_old_svalue): Drop unused decl.
(sm_context::get_new_program_state): New vfunc.
(make_va_list_state_machine): New decl.
* varargs.cc: New file.
gcc/testsuite/ChangeLog:
PR analyzer/105103
* gcc.dg/analyzer/stdarg-1.c: New test.
* gcc.dg/analyzer/stdarg-2.c: New test.
* gcc.dg/analyzer/stdarg-fmtstring-1.c: New test.
* gcc.dg/analyzer/stdarg-lto-1-a.c: New test.
* gcc.dg/analyzer/stdarg-lto-1-b.c: New test.
* gcc.dg/analyzer/stdarg-lto-1.h: New test.
* gcc.dg/analyzer/stdarg-sentinel-1.c: New test.
* gcc.dg/analyzer/stdarg-types-1.c: New test.
* gcc.dg/analyzer/stdarg-types-2.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/doc')
-rw-r--r-- | gcc/doc/invoke.texi | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7a35d96..e8e6d4e 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -464,6 +464,10 @@ Objective-C and Objective-C++ Dialects}. -Wno-analyzer-use-after-free @gol -Wno-analyzer-use-of-pointer-in-stale-stack-frame @gol -Wno-analyzer-use-of-uninitialized-value @gol +-Wno-analyzer-va-arg-type-mismatch @gol +-Wno-analyzer-va-list-exhausted @gol +-Wno-analyzer-va-list-leak @gol +-Wno-analyzer-va-list-use-after-va-end @gol -Wno-analyzer-write-to-const @gol -Wno-analyzer-write-to-string-literal @gol } @@ -9689,6 +9693,10 @@ Enabling this option effectively enables the following warnings: -Wanalyzer-use-after-free @gol -Wanalyzer-use-of-pointer-in-stale-stack-frame @gol -Wanalyzer-use-of-uninitialized-value @gol +-Wanalyzer-va-arg-type-mismatch @gol +-Wanalyzer-va-list-exhausted @gol +-Wanalyzer-va-list-leak @gol +-Wanalyzer-va-list-use-after-va-end @gol -Wanalyzer-write-to-const @gol -Wanalyzer-write-to-string-literal @gol } @@ -9971,6 +9979,53 @@ to disable it. This diagnostic warns for paths through the code in which a pointer is dereferenced that points to a variable in a stale stack frame. +@item -Wno-analyzer-va-arg-type-mismatch +@opindex Wanalyzer-va-arg-type-mismatch +@opindex Wno-analyzer-va-arg-type-mismatch +This warning requires @option{-fanalyzer}, which enables it; use +@option{-Wno-analyzer-va-arg-type-mismatch} +to disable it. + +This diagnostic warns for interprocedural paths through the code for which +the analyzer detects an attempt to use @code{va_arg} to extract a value +passed to a variadic call, but uses a type that does not match that of +the expression passed to the call. + +@item -Wno-analyzer-va-list-exhausted +@opindex Wanalyzer-va-list-exhausted +@opindex Wno-analyzer-va-list-exhausted +This warning requires @option{-fanalyzer}, which enables it; use +@option{-Wno-analyzer-va-list-exhausted} +to disable it. + +This diagnostic warns for interprocedural paths through the code for which +the analyzer detects an attempt to use @code{va_arg} to access the next +value passed to a variadic call, but all of the values in the +@code{va_list} have already been consumed. + +@item -Wno-analyzer-va-list-leak +@opindex Wanalyzer-va-list-leak +@opindex Wno-analyzer-va-list-leak +This warning requires @option{-fanalyzer}, which enables it; use +@option{-Wno-analyzer-va-list-leak} +to disable it. + +This diagnostic warns for interprocedural paths through the code for which +the analyzer detects that @code{va_start} or @code{va_copy} has been called +on a @code{va_list} without a corresponding call to @code{va_end}. + +@item -Wno-analyzer-va-list-use-after-va-end +@opindex Wanalyzer-va-list-use-after-va-end +@opindex Wno-analyzer-va-list-use-after-va-end +This warning requires @option{-fanalyzer}, which enables it; use +@option{-Wno-analyzer-va-list-use-after-va-end} +to disable it. + +This diagnostic warns for interprocedural paths through the code for which +the analyzer detects an attempt to use a @code{va_list} after +@code{va_end} has been called on it. +@code{va_list}. + @item -Wno-analyzer-write-to-const @opindex Wanalyzer-write-to-const @opindex Wno-analyzer-write-to-const |