public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-8627] analyzer: fix -Wanalyzer-allocation-size false +ve on Linux kernel's round_up macro [PR113654]
@ 2024-01-30 13:20 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2024-01-30 13:20 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9f382376660069e49290fdb51861abdec63519c7

commit r14-8627-g9f382376660069e49290fdb51861abdec63519c7
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Tue Jan 30 08:17:47 2024 -0500

    analyzer: fix -Wanalyzer-allocation-size false +ve on Linux kernel's round_up macro [PR113654]
    
    gcc/analyzer/ChangeLog:
            PR analyzer/113654
            * region-model.cc (is_round_up): New.
            (is_multiple_p): New.
            (is_dubious_capacity): New.
            (region_model::check_region_size): Move usage of size_visitor into
            is_dubious_capacity.
    
    gcc/testsuite/ChangeLog:
            PR analyzer/113654
            * c-c++-common/analyzer/allocation-size-pr113654-1.c: New test.
    
    Signed-off-by: David Malcolm <dmalcolm@redhat.com>

Diff:
---
 gcc/analyzer/region-model.cc                       | 75 +++++++++++++++++++++-
 .../analyzer/allocation-size-pr113654-1.c          | 52 +++++++++++++++
 2 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index ba82f46c1887..082972f9d294 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -3349,6 +3349,76 @@ private:
   svalue_set result_set; /* Used as a mapping of svalue*->bool.  */
 };
 
+/* Return true if SIZE_CST is a power of 2, and we have
+   CAPACITY_SVAL == ((X | (Y - 1) ) + 1), since it is then a multiple
+   of SIZE_CST, as used by Linux kernel's round_up macro.  */
+
+static bool
+is_round_up (tree size_cst,
+	     const svalue *capacity_sval)
+{
+  if (!integer_pow2p (size_cst))
+    return false;
+  const binop_svalue *binop_sval = capacity_sval->dyn_cast_binop_svalue ();
+  if (!binop_sval)
+    return false;
+  if (binop_sval->get_op () != PLUS_EXPR)
+    return false;
+  tree rhs_cst = binop_sval->get_arg1 ()->maybe_get_constant ();
+  if (!rhs_cst)
+    return false;
+  if (!integer_onep (rhs_cst))
+    return false;
+
+  /* We have CAPACITY_SVAL == (LHS + 1) for some LHS expression.  */
+
+  const binop_svalue *lhs_binop_sval
+    = binop_sval->get_arg0 ()->dyn_cast_binop_svalue ();
+  if (!lhs_binop_sval)
+    return false;
+  if (lhs_binop_sval->get_op () != BIT_IOR_EXPR)
+    return false;
+
+  tree inner_rhs_cst = lhs_binop_sval->get_arg1 ()->maybe_get_constant ();
+  if (!inner_rhs_cst)
+    return false;
+
+  if (wi::to_widest (inner_rhs_cst) + 1 != wi::to_widest (size_cst))
+    return false;
+  return true;
+}
+
+/* Return true if CAPACITY_SVAL is known to be a multiple of SIZE_CST.  */
+
+static bool
+is_multiple_p (tree size_cst,
+	       const svalue *capacity_sval)
+{
+  if (const svalue *sval = capacity_sval->maybe_undo_cast ())
+    return is_multiple_p (size_cst, sval);
+
+  if (is_round_up (size_cst, capacity_sval))
+    return true;
+
+  return false;
+}
+
+/* Return true if we should emit a dubious_allocation_size warning
+   on assigning a region of capacity CAPACITY_SVAL bytes to a pointer
+   of type with size SIZE_CST, where CM expresses known constraints.  */
+
+static bool
+is_dubious_capacity (tree size_cst,
+		     const svalue *capacity_sval,
+		     constraint_manager *cm)
+{
+  if (is_multiple_p (size_cst, capacity_sval))
+    return false;
+  size_visitor v (size_cst, capacity_sval, cm);
+  return v.is_dubious_capacity ();
+}
+
+
 /* Return true if a struct or union either uses the inheritance pattern,
    where the first field is a base struct, or the flexible array member
    pattern, where the last field is an array without a specified size.  */
@@ -3456,8 +3526,9 @@ region_model::check_region_size (const region *lhs_reg, const svalue *rhs_sval,
       {
 	if (!is_struct)
 	  {
-	    size_visitor v (pointee_size_tree, capacity, m_constraints);
-	    if (v.is_dubious_capacity ())
+	    if (is_dubious_capacity (pointee_size_tree,
+				     capacity,
+				     m_constraints))
 	      {
 		tree expr = get_representative_tree (capacity);
 		ctxt->warn (make_unique <dubious_allocation_size> (lhs_reg,
diff --git a/gcc/testsuite/c-c++-common/analyzer/allocation-size-pr113654-1.c b/gcc/testsuite/c-c++-common/analyzer/allocation-size-pr113654-1.c
new file mode 100644
index 000000000000..b7bfc5fec72a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/analyzer/allocation-size-pr113654-1.c
@@ -0,0 +1,52 @@
+/* Adapted from include/linux/math.h  */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+
+/* Reduced from Linux kernel's drivers/gpu/drm/i915/display/intel_bios.c  */
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long __kernel_size_t;
+typedef __kernel_size_t size_t;
+
+extern __attribute__((__alloc_size__(1))) __attribute__((__malloc__))
+void* kzalloc(size_t size);
+
+typedef struct
+{
+  u32 reg;
+} i915_reg_t;
+struct intel_uncore;
+struct intel_uncore_funcs
+{
+  u32 (*mmio_readl)(struct intel_uncore* uncore, i915_reg_t r);
+};
+struct intel_uncore
+{
+  void* regs;
+  struct intel_uncore_funcs funcs;
+};
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__))
+__attribute__((no_instrument_function)) u32
+intel_uncore_read(struct intel_uncore* uncore, i915_reg_t reg)
+{
+  return uncore->funcs.mmio_readl(uncore, reg);
+}
+struct drm_i915_private
+{
+  struct intel_uncore uncore;
+};
+struct vbt_header*
+spi_oprom_get_vbt(struct drm_i915_private* i915)
+{
+  u16 vbt_size;
+  u32* vbt;
+  vbt_size =
+    intel_uncore_read(&i915->uncore, ((const i915_reg_t){ .reg = (0x102040) }));
+  vbt_size &= 0xffff;
+  vbt = (u32*)kzalloc(round_up (vbt_size, 4)); /* { dg-bogus "allocated buffer size is not a multiple of the pointee's size" "PR analyzer/113654" } */
+  if (!vbt)
+    goto err_not_found;
+  return (struct vbt_header*)vbt;
+err_not_found:
+  return ((struct vbt_header*)0);
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-30 13:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-30 13:20 [gcc r14-8627] analyzer: fix -Wanalyzer-allocation-size false +ve on Linux kernel's round_up macro [PR113654] David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).