On Thu, Aug 29, 2024 at 06:58:12PM -0400, David Malcolm wrote:
> The following patch rewrites the internals of pp_format.

> The tokens and token lists are allocated on the chunk_obstack, and so
> there's no additional heap activity required, with the memory reclaimed
> when the chunk_obstack is freed after phase 3 of formatting.

> +static void *
> +allocate_object (size_t sz, obstack &s)
> +{
> +  /* We must not be half-way through an object.  */
> +  gcc_assert (obstack_base (&s) == obstack_next_free (&s));
> +
> +  obstack_grow (&s, obstack_base (&s), sz);
> +  void *buf = obstack_finish (&s);
> +  return buf;
>  }

I think this is wrong.  I hoped it would be the reason of the
unexpected libstdc++ warnings on certain architectures after
seeing
==4027220== Source and destination overlap in memcpy(0x4627154, 0x4627154, 12)
==4027220==    at 0x404B93E: memcpy (vg_replace_strmem.c:1123)
==4027220==    by 0xAAD5618: allocate_object(unsigned int, obstack&) 
(pretty-print.cc:1183)
==4027220==    by 0xAAD8C0E: operator new (pretty-print.cc:1210)
==4027220==    by 0xAAD8C0E: make (pretty-print-format-impl.h:305)
==4027220==    by 0xAAD8C0E: format_phase_1 (pretty-print.cc:1659)
==4027220==    by 0xAAD8C0E: pretty_printer::format(text_info&) 
(pretty-print.cc:1618)
==4027220==    by 0xAAA840E: pp_format (pretty-print.h:583)
==4027220==    by 0xAAA840E: 
diagnostic_context::report_diagnostic(diagnostic_info*) (diagnostic.cc:1260)
==4027220==    by 0xAAA8703: 
diagnostic_context::diagnostic_impl(rich_location*, diagnostic_metadata const*, 
diagnostic_option_id, char const*, char**, diagnostic_t) (diagnostic.cc:1404)
==4027220==    by 0xAAB8682: warning(diagnostic_option_id, char const*, ...) 
(diagnostic-global-context.cc:166)
==4027220==    by 0x97725F5: warn_deprecated_use(tree_node*, tree_node*) 
(tree.cc:12485)
==4027220==    by 0x8B6694B: mark_used(tree_node*, int) (decl2.cc:6121)
==4027220==    by 0x8C9E25E: tsubst_expr(tree_node*, tree_node*, int, 
tree_node*) [clone .part.0] (pt.cc:21626)
==4027220==    by 0x8C9E5E6: tsubst_expr(tree_node*, tree_node*, int, 
tree_node*) [clone .part.0] (pt.cc:20935)
==4027220==    by 0x8C9E1D7: tsubst_expr(tree_node*, tree_node*, int, 
tree_node*) [clone .part.0] (pt.cc:20424)
==4027220==    by 0x8C9DF2E: tsubst_expr(tree_node*, tree_node*, int, 
tree_node*) [clone .part.0] (pt.cc:20496)
==4027220== 
etc. valgrind warnings, unfortunately it is not, but still
I think this is a bug.
If the obstack has enough space in it, i.e. if obstack_room (&s) >= sz,
then obstack_grow from obstack_base will copy uninitialized bytes
through memcpy (obstack_base (&s), obstack_base (&s), sz);
(which pedantically isn't valid due to the overlap, and so
the reason why valgrind complains, but in reality I think most
implementations can handle it fine, after all, we also use it for
structure assignments which could have full or no overlap but never
partial).
If obstack_room (&s) < sz, then obstack_grow will first
_obstack_newchunk (&s, sz); which will allocate new memory and
copy the existing data of the object (but the above assertion
guartantees it will copy 0 bytes) and then the memcpy copies
sz bytes from the old base to the new (if unlucky, that could crash
as there could be end of page and unmapped next page in between).

I think we should use obstack_blank instead of obstack_grow, which
does everything obstack_grow does, except for the memcpy of the
uninitialized data.

Bootstrapped/regtested on i686-linux, ok for trunk?

2024-09-25  Jakub Jelinek  <ja...@redhat.com>

        * pretty-print.cc (allocate_object): Use obstack_blank rather than
        obstack_grow.

--- gcc/pretty-print.cc.jj      2024-09-24 15:14:54.116162039 +0200
+++ gcc/pretty-print.cc 2024-09-25 22:12:57.776029725 +0200
@@ -1180,7 +1180,7 @@ allocate_object (size_t sz, obstack &s)
   /* We must not be half-way through an object.  */
   gcc_assert (obstack_base (&s) == obstack_next_free (&s));
 
-  obstack_grow (&s, obstack_base (&s), sz);
+  obstack_blank (&s, sz);
   void *buf = obstack_finish (&s);
   return buf;
 }


        Jakub

Reply via email to