From 617bd59c659dcf6e5391409a2e9f64f75e905a96 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 15 Feb 2024 16:01:36 -0500 Subject: [PATCH] analyzer: remove offset_region size overloads [PR111266] PR analyzer/111266 reports a missing -Wanalyzer-out-of-bounds when accessing relative to a concrete byte offset. Root cause is that offset_region::get_{byte,bit}_size_sval were attempting to compute the size that's valid to access, rather than the size of the access attempt. Fixed by removing these vfunc overrides from offset_region as the base class implementation does the right thing. gcc/analyzer/ChangeLog: PR analyzer/111266 * region.cc (offset_region::get_byte_size_sval): Delete. (offset_region::get_bit_size_sval): Delete. * region.h (region::get_byte_size): Add comment clarifying that this relates to the size of the access, rather than the size that's valid to access. (region::get_bit_size): Likewise. (region::get_byte_size_sval): Likewise. (region::get_bit_size_sval): Likewise. (offset_region::get_byte_size_sval): Delete. (offset_region::get_bit_size_sval): Delete. gcc/testsuite/ChangeLog: PR analyzer/111266 * c-c++-common/analyzer/out-of-bounds-pr111266.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/region.cc | 48 ------------------- gcc/analyzer/region.h | 20 ++++---- .../analyzer/out-of-bounds-pr111266.c | 11 +++++ 3 files changed, 23 insertions(+), 56 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr111266.c diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 249852a7da8..50821a59230 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -1990,54 +1990,6 @@ offset_region::get_relative_symbolic_offset (region_model_manager *mgr return get_byte_offset (); } -/* Implementation of region::get_byte_size_sval vfunc for offset_region. */ - -const svalue * -offset_region::get_byte_size_sval (region_model_manager *mgr) const -{ - tree offset_cst = get_byte_offset ()->maybe_get_constant (); - byte_size_t byte_size; - /* If the offset points in the middle of the region, - return the remaining bytes. */ - if (get_byte_size (&byte_size) && offset_cst) - { - byte_size_t offset = wi::to_offset (offset_cst); - byte_range r (0, byte_size); - if (r.contains_p (offset)) - { - tree remaining_byte_size = wide_int_to_tree (size_type_node, - byte_size - offset); - return mgr->get_or_create_constant_svalue (remaining_byte_size); - } - } - - return region::get_byte_size_sval (mgr); -} - -/* Implementation of region::get_bit_size_sval vfunc for offset_region. */ - -const svalue * -offset_region::get_bit_size_sval (region_model_manager *mgr) const -{ - tree offset_cst = get_bit_offset (mgr)->maybe_get_constant (); - bit_size_t bit_size; - /* If the offset points in the middle of the region, - return the remaining bits. */ - if (get_bit_size (&bit_size) && offset_cst) - { - bit_size_t offset = wi::to_offset (offset_cst); - bit_range r (0, bit_size); - if (r.contains_p (offset)) - { - tree remaining_bit_size = wide_int_to_tree (size_type_node, - bit_size - offset); - return mgr->get_or_create_constant_svalue (remaining_bit_size); - } - } - - return region::get_bit_size_sval (mgr); -} - /* class sized_region : public region. */ /* Implementation of region::accept vfunc for sized_region. */ diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h index 3d3ff8eccbf..70557babbc0 100644 --- a/gcc/analyzer/region.h +++ b/gcc/analyzer/region.h @@ -187,20 +187,28 @@ public: /* Attempt to get the size of this region as a concrete number of bytes. If successful, return true and write the size to *OUT. - Otherwise return false. */ + Otherwise return false. + This is the accessed size, not necessarily the size that's valid to + access. */ virtual bool get_byte_size (byte_size_t *out) const; /* Attempt to get the size of this region as a concrete number of bits. If successful, return true and write the size to *OUT. - Otherwise return false. */ + Otherwise return false. + This is the accessed size, not necessarily the size that's valid to + access. */ virtual bool get_bit_size (bit_size_t *out) const; /* Get a symbolic value describing the size of this region in bytes - (which could be "unknown"). */ + (which could be "unknown"). + This is the accessed size, not necessarily the size that's valid to + access. */ virtual const svalue *get_byte_size_sval (region_model_manager *mgr) const; /* Get a symbolic value describing the size of this region in bits - (which could be "unknown"). */ + (which could be "unknown"). + This is the accessed size, not necessarily the size that's valid to + access. */ virtual const svalue *get_bit_size_sval (region_model_manager *mgr) const; /* Attempt to get the offset in bits of this region relative to its parent. @@ -978,10 +986,6 @@ public: bool get_relative_concrete_offset (bit_offset_t *out) const final override; const svalue *get_relative_symbolic_offset (region_model_manager *mgr) const final override; - const svalue * get_byte_size_sval (region_model_manager *mgr) - const final override; - const svalue * get_bit_size_sval (region_model_manager *mgr) - const final override; private: const svalue *m_byte_offset; diff --git a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr111266.c b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr111266.c new file mode 100644 index 00000000000..cee36630baa --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr111266.c @@ -0,0 +1,11 @@ +#include +void *malloc (__SIZE_TYPE__); +void free (void *); + +void test_binop2 () +{ + char *p = (char *) malloc (4); + int32_t *i = (int32_t *) (p + 3); + *i = 20042; /* { dg-warning "heap-based buffer overflow" } */ + free (p); +}