aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-08-01 05:53:37 +0200
committerMartin Liska <mliska@suse.cz>2022-08-01 05:53:37 +0200
commit89eca196c99645ee1abefcf8b4a9dd84edd87ad6 (patch)
tree185cc8907ce37e82132f395cb52611f029215355 /gcc/analyzer
parent3a4cd5dc6faca8fed7fa256c4c06f4999b5a1f9c (diff)
parent4a7274ddc4970c1ad011343ed285d6219dffa396 (diff)
downloadgcc-89eca196c99645ee1abefcf8b4a9dd84edd87ad6.zip
gcc-89eca196c99645ee1abefcf8b4a9dd84edd87ad6.tar.gz
gcc-89eca196c99645ee1abefcf8b4a9dd84edd87ad6.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc/analyzer')
-rw-r--r--gcc/analyzer/ChangeLog19
-rw-r--r--gcc/analyzer/analyzer.opt4
-rw-r--r--gcc/analyzer/region-model-impl-calls.cc117
-rw-r--r--gcc/analyzer/region-model.cc6
-rw-r--r--gcc/analyzer/region-model.h1
-rw-r--r--gcc/analyzer/region.h52
-rw-r--r--gcc/analyzer/sm-malloc.cc1
-rw-r--r--gcc/analyzer/sm-taint.cc1
8 files changed, 180 insertions, 21 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index d10a5c8..d1cb3ad 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,22 @@
+2022-07-28 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/105893
+ * analyzer.opt (Wanalyzer-putenv-of-auto-var): New.
+ * region-model-impl-calls.cc (class putenv_of_auto_var): New.
+ (region_model::impl_call_putenv): New.
+ * region-model.cc (region_model::on_call_pre): Handle putenv.
+ * region-model.h (region_model::impl_call_putenv): New decl.
+
+2022-07-28 David Malcolm <dmalcolm@redhat.com>
+
+ * sm-malloc.cc (free_of_non_heap::emit): Add comment about CWE.
+ * sm-taint.cc (tainted_size::emit): Likewise.
+
+2022-07-28 David Malcolm <dmalcolm@redhat.com>
+
+ * region.h: Add notes to the comment describing the region
+ class hierarchy.
+
2022-07-27 Immad Mir <mirimmad@outlook.com>
PR analyzer/106286
diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index 5021376..808ff36 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -126,6 +126,10 @@ Wanalyzer-null-dereference
Common Var(warn_analyzer_null_dereference) Init(1) Warning
Warn about code paths in which a NULL pointer is dereferenced.
+Wanalyzer-putenv-of-auto-var
+Common Var(warn_analyzer_putenv_of_auto_var) Init(1) Warning
+Warn about code paths in which an on-stack buffer is passed to putenv.
+
Wanalyzer-shift-count-negative
Common Var(warn_analyzer_shift_count_negative) Init(1) Warning
Warn about code paths in which a shift with negative count is attempted.
diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc
index 8c38e92..3f821ff 100644
--- a/gcc/analyzer/region-model-impl-calls.cc
+++ b/gcc/analyzer/region-model-impl-calls.cc
@@ -549,6 +549,123 @@ region_model::impl_call_memset (const call_details &cd)
fill_region (sized_dest_reg, fill_value_u8);
}
+/* A subclass of pending_diagnostic for complaining about 'putenv'
+ called on an auto var. */
+
+class putenv_of_auto_var
+: public pending_diagnostic_subclass<putenv_of_auto_var>
+{
+public:
+ putenv_of_auto_var (tree fndecl, const region *reg)
+ : m_fndecl (fndecl), m_reg (reg),
+ m_var_decl (reg->get_base_region ()->maybe_get_decl ())
+ {
+ }
+
+ const char *get_kind () const final override
+ {
+ return "putenv_of_auto_var";
+ }
+
+ bool operator== (const putenv_of_auto_var &other) const
+ {
+ return (m_fndecl == other.m_fndecl
+ && m_reg == other.m_reg
+ && same_tree_p (m_var_decl, other.m_var_decl));
+ }
+
+ int get_controlling_option () const final override
+ {
+ return OPT_Wanalyzer_putenv_of_auto_var;
+ }
+
+ bool emit (rich_location *rich_loc) final override
+ {
+ auto_diagnostic_group d;
+ diagnostic_metadata m;
+
+ /* SEI CERT C Coding Standard: "POS34-C. Do not call putenv() with a
+ pointer to an automatic variable as the argument". */
+ diagnostic_metadata::precanned_rule
+ rule ("POS34-C", "https://wiki.sei.cmu.edu/confluence/x/6NYxBQ");
+ m.add_rule (rule);
+
+ bool warned;
+ if (m_var_decl)
+ warned = warning_meta (rich_loc, m, get_controlling_option (),
+ "%qE on a pointer to automatic variable %qE",
+ m_fndecl, m_var_decl);
+ else
+ warned = warning_meta (rich_loc, m, get_controlling_option (),
+ "%qE on a pointer to an on-stack buffer",
+ m_fndecl);
+ if (warned)
+ {
+ if (m_var_decl)
+ inform (DECL_SOURCE_LOCATION (m_var_decl),
+ "%qE declared on stack here", m_var_decl);
+ inform (rich_loc->get_loc (), "perhaps use %qs rather than %qE",
+ "setenv", m_fndecl);
+ }
+
+ return warned;
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) final override
+ {
+ if (m_var_decl)
+ return ev.formatted_print ("%qE on a pointer to automatic variable %qE",
+ m_fndecl, m_var_decl);
+ else
+ return ev.formatted_print ("%qE on a pointer to an on-stack buffer",
+ m_fndecl);
+ }
+
+ void mark_interesting_stuff (interesting_t *interest) final override
+ {
+ if (!m_var_decl)
+ interest->add_region_creation (m_reg->get_base_region ());
+ }
+
+private:
+ tree m_fndecl; // non-NULL
+ const region *m_reg; // non-NULL
+ tree m_var_decl; // could be NULL
+};
+
+/* Handle the on_call_pre part of "putenv".
+
+ In theory we could try to model the state of the environment variables
+ for the process; for now we merely complain about putenv of regions
+ on the stack. */
+
+void
+region_model::impl_call_putenv (const call_details &cd)
+{
+ tree fndecl = cd.get_fndecl_for_call ();
+ gcc_assert (fndecl);
+ region_model_context *ctxt = cd.get_ctxt ();
+ const svalue *ptr_sval = cd.get_arg_svalue (0);
+ const region *reg = deref_rvalue (ptr_sval, cd.get_arg_tree (0), ctxt);
+ m_store.mark_as_escaped (reg);
+ enum memory_space mem_space = reg->get_memory_space ();
+ switch (mem_space)
+ {
+ default:
+ gcc_unreachable ();
+ case MEMSPACE_UNKNOWN:
+ case MEMSPACE_CODE:
+ case MEMSPACE_GLOBALS:
+ case MEMSPACE_HEAP:
+ case MEMSPACE_READONLY_DATA:
+ break;
+ case MEMSPACE_STACK:
+ if (ctxt)
+ ctxt->warn (new putenv_of_auto_var (fndecl, reg));
+ break;
+ }
+}
+
/* Handle the on_call_pre part of "operator new". */
void
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index f7df2fc..a140f4d 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1539,6 +1539,12 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
impl_call_memset (cd);
return false;
}
+ else if (is_named_call_p (callee_fndecl, "putenv", call, 1)
+ && POINTER_TYPE_P (cd.get_arg_type (0)))
+ {
+ impl_call_putenv (cd);
+ return false;
+ }
else if (is_named_call_p (callee_fndecl, "strchr", call, 2)
&& POINTER_TYPE_P (cd.get_arg_type (0)))
{
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 42f8abe..a9657e0 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -630,6 +630,7 @@ class region_model
void impl_call_malloc (const call_details &cd);
void impl_call_memcpy (const call_details &cd);
void impl_call_memset (const call_details &cd);
+ void impl_call_putenv (const call_details &cd);
void impl_call_realloc (const call_details &cd);
void impl_call_strchr (const call_details &cd);
void impl_call_strcpy (const call_details &cd);
diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h
index 1067748..a5b3029 100644
--- a/gcc/analyzer/region.h
+++ b/gcc/analyzer/region.h
@@ -72,27 +72,37 @@ enum region_kind
region
space_region
- frame_region (RK_FRAME)
- globals_region (RK_GLOBALS)
- code_region (RK_CODE)
- stack_region (RK_STACK)
- heap_region (RK_HEAP)
- root_region (RK_ROOT)
- function_region (RK_FUNCTION)
- label_region (RK_LABEL)
- symbolic_region (RK_SYMBOLIC)
- decl_region (RK_DECL),
- field_region (RK_FIELD)
- element_region (RK_ELEMENT)
- offset_region (RK_OFFSET)
- sized_region (RK_SIZED)
- cast_region (RK_CAST)
- heap_allocated_region (RK_HEAP_ALLOCATED)
- alloca_region (RK_ALLOCA)
- string_region (RK_STRING)
- bit_range_region (RK_BIT_RANGE)
- var_arg_region (RK_VAR_ARG)
- unknown_region (RK_UNKNOWN). */
+ frame_region (RK_FRAME): a function frame on the stack
+ globals_region (RK_GLOBALS): holds globals variables (data and bss)
+ code_region (RK_CODE): represents the code segment, containing functions
+ stack_region (RK_STACK): a stack, containing all stack frames
+ heap_region (RK_HEAP): the heap, containing heap_allocated_regions
+ root_region (RK_ROOT): the top-level region
+ function_region (RK_FUNCTION): the code for a particular function
+ label_region (RK_LABEL): a particular label within a function
+ symbolic_region (RK_SYMBOLIC): dereferencing a symbolic pointer
+ decl_region (RK_DECL): the memory occupied by a particular global, local,
+ or SSA name
+ field_region (RK_FIELD): the memory occupied by a field within a struct
+ or union
+ element_region (RK_ELEMENT): an element within an array
+ offset_region (RK_OFFSET): a byte-offset within another region, for
+ handling pointer arithmetic as a region
+ sized_region (RK_SIZED): a subregion of symbolic size (in bytes)
+ within its parent
+ cast_region (RK_CAST): a region that views another region using a
+ different type
+ heap_allocated_region (RK_HEAP_ALLOCATED): an untyped region dynamically
+ allocated on the heap via
+ "malloc" or similar
+ alloca_region (RK_ALLOCA): an untyped region dynamically allocated on the
+ stack via "alloca"
+ string_region (RK_STRING): a region for a STRING_CST
+ bit_range_region (RK_BIT_RANGE): a region for a specific range of bits
+ within another region
+ var_arg_region (RK_VAR_ARG): a region for the N-th vararg within a
+ frame_region for a variadic call
+ unknown_region (RK_UNKNOWN): for handling unimplemented tree codes. */
/* Abstract base class for representing ways of accessing chunks of memory.
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 608aceb..73c549f 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -1300,6 +1300,7 @@ public:
bool emit (rich_location *rich_loc) final override
{
+ /* "CWE-401: Missing Release of Memory after Effective Lifetime". */
diagnostic_metadata m;
m.add_cwe (401);
if (m_arg)
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index 51bfe06..549373b 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -435,6 +435,7 @@ public:
bool emit (rich_location *rich_loc) override
{
+ /* "CWE-129: Improper Validation of Array Index". */
diagnostic_metadata m;
m.add_cwe (129);
if (m_arg)