On Fri, 2023-09-01 at 00:04 +0200, priour...@gmail.com wrote:
> Hi, > > Succesfully regstrapped off trunk 7f2ed06ddc825e8a4e0edfd1d66b5156e6dc1d34 > on x86_64-linux-gnu. > > Is it OK for trunk ? Hi Benjamin. Thanks for the patch. It's OK as-is, but it doesn't cover every case... [...snip...] > diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc > index 66fb0fe871e..8d60e928b15 100644 > --- a/gcc/analyzer/call-details.cc > +++ b/gcc/analyzer/call-details.cc > @@ -295,6 +295,17 @@ call_details::get_arg_svalue (unsigned idx) const > return m_model->get_rvalue (arg, m_ctxt); > } > > +/* If argument IDX's svalue at the callsite is a region_svalue, > + return the region it points to. > + Otherwise return NULL. */ > + > +const region * > +call_details::maybe_get_arg_region (unsigned idx) const > +{ > + const svalue *sval = get_arg_svalue (idx); > + return sval->maybe_get_region (); > +} > + Is this the correct thing to be doing? It's used in the following... [...snip...] > diff --git a/gcc/analyzer/kf-lang-cp.cc b/gcc/analyzer/kf-lang-cp.cc > index 393b4f25e79..4450892dfa2 100644 > --- a/gcc/analyzer/kf-lang-cp.cc > +++ b/gcc/analyzer/kf-lang-cp.cc [...snip...] > @@ -54,28 +90,75 @@ public: > region_model *model = cd.get_model (); > region_model_manager *mgr = cd.get_manager (); > const svalue *size_sval = cd.get_arg_svalue (0); > - const region *new_reg > - = model->get_or_create_region_for_heap_alloc (size_sval, cd.get_ctxt > ()); > - if (cd.get_lhs_type ()) > + region_model_context *ctxt = cd.get_ctxt (); > + const gcall *call = cd.get_call_stmt (); > + > + /* If the call was actually a placement new, check that accessing > + the buffer lhs is placed into does not result in out-of-bounds. */ > + if (is_placement_new_p (call)) > { > - const svalue *ptr_sval > - = mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg); > - cd.maybe_set_lhs (ptr_sval); > + const region *ptr_reg = cd.maybe_get_arg_region (1); > + if (ptr_reg && cd.get_lhs_type ()) > + { ...which will only fire if arg 1 is a region_svalue. This won't trigger if you have e.g. a binop_svalue for pointer arithmetic. What happens e.g. for this one-off-the-end bug: void *p = malloc (4); if (!p) return; int32_t *i = ::new (p + 1) int32_t; *i = 42; So maybe call_details::maybe_get_arg_region should instead be: /* Return the region that argument IDX points to. */ const region * call_details::deref_ptr_arg (unsigned idx) const { const svalue *ptr_sval = get_arg_svalue (idx); return m_model->deref_rvalue (ptr_sval, get_arg_tree (idx), m_ctxt); } (caveat: I didn't test this) > + const region *base_reg = ptr_reg->get_base_region (); > + const svalue *num_bytes_sval = cd.get_arg_svalue (0); > + const region *sized_new_reg > + = mgr->get_sized_region (base_reg, > + cd.get_lhs_type (), > + num_bytes_sval); Why do you use the base_reg here, rather than just ptr_reg? In the example above, the *(p + 1) has base region heap_allocated_region, but the ptr_reg is one byte higher; hence check_region_for_write of 4 bytes ought to detect a problem with writing 4 bytes to *(p + 1), but wouldn't complain about the write to *p. ...assuming that I'm reading this code correctly. > + model->check_region_for_write (sized_new_reg, > + nullptr, > + ctxt); > + const svalue *ptr_sval > + = mgr->get_ptr_svalue (cd.get_lhs_type (), sized_new_reg); > + cd.maybe_set_lhs (ptr_sval); > + } > + } [...snip...] The patch is OK for trunk as is; but please can you look into the above. If the above is a problem, you can either do another version of the patch, or do it as a followup patch (whichever you're more comfortable with, but it might be best to get the patch into trunk as-is, given that the GSoC period is nearly over). Thanks Dave