public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] middle-end/101292 - invalid memory access with warning control
@ 2022-01-17 14:32 Richard Biener
  2022-01-17 18:12 ` Martin Sebor
  0 siblings, 1 reply; 5+ messages in thread
From: Richard Biener @ 2022-01-17 14:32 UTC (permalink / raw)
  To: gcc-patches

The warning control falls into the C++ trap of using a reference
to old hashtable contents for a put operation which can end up
re-allocating that before reading from the old freed referenced to
source.  Fixed by introducing a temporary.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

2022-01-17  Richard Biener  <rguenther@suse.de>

	PR middle-end/101292
	* diagnostic-spec.c (copy_warning): Make sure to not
	reference old hashtable content on possible resize.
	* warning-control.cc (copy_warning): Likewise.
---
 gcc/diagnostic-spec.c  | 5 ++++-
 gcc/warning-control.cc | 3 ++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index a8af229d677..4341ccfaae9 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -195,7 +195,10 @@ copy_warning (location_t to, location_t from)
   else
     {
       if (from_spec)
-	nowarn_map->put (to, *from_spec);
+	{
+	  nowarn_spec_t tem = *from_spec;
+	  nowarn_map->put (to, tem);
+	}
       else
 	nowarn_map->remove (to);
     }
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index f9808bf4392..fa39ecab421 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -206,7 +206,8 @@ void copy_warning (ToType to, FromType from)
 	  gcc_assert (supp);
 
 	  gcc_checking_assert (nowarn_map);
-	  nowarn_map->put (to_loc, *from_spec);
+	  nowarn_spec_t tem = *from_spec;
+	  nowarn_map->put (to_loc, tem);
 	}
       else
 	{
-- 
2.31.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] middle-end/101292 - invalid memory access with warning control
  2022-01-17 14:32 [PATCH] middle-end/101292 - invalid memory access with warning control Richard Biener
@ 2022-01-17 18:12 ` Martin Sebor
  2022-01-18  8:36   ` Richard Biener
  0 siblings, 1 reply; 5+ messages in thread
From: Martin Sebor @ 2022-01-17 18:12 UTC (permalink / raw)
  To: Richard Biener, gcc-patches

On 1/17/22 07:32, Richard Biener via Gcc-patches wrote:
> The warning control falls into the C++ trap of using a reference
> to old hashtable contents for a put operation which can end up
> re-allocating that before reading from the old freed referenced to
> source.  Fixed by introducing a temporary.

I think a better place to fix this and avoid the gotcha once and
for all is in the GCC hash_map: C++ containers are expected to
handle the insertion of own elements gracefully.

Martin

> 
> Bootstrap & regtest running on x86_64-unknown-linux-gnu.
> 
> 2022-01-17  Richard Biener  <rguenther@suse.de>
> 
> 	PR middle-end/101292
> 	* diagnostic-spec.c (copy_warning): Make sure to not
> 	reference old hashtable content on possible resize.
> 	* warning-control.cc (copy_warning): Likewise.
> ---
>   gcc/diagnostic-spec.c  | 5 ++++-
>   gcc/warning-control.cc | 3 ++-
>   2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
> index a8af229d677..4341ccfaae9 100644
> --- a/gcc/diagnostic-spec.c
> +++ b/gcc/diagnostic-spec.c
> @@ -195,7 +195,10 @@ copy_warning (location_t to, location_t from)
>     else
>       {
>         if (from_spec)
> -	nowarn_map->put (to, *from_spec);
> +	{
> +	  nowarn_spec_t tem = *from_spec;
> +	  nowarn_map->put (to, tem);
> +	}
>         else
>   	nowarn_map->remove (to);
>       }
> diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
> index f9808bf4392..fa39ecab421 100644
> --- a/gcc/warning-control.cc
> +++ b/gcc/warning-control.cc
> @@ -206,7 +206,8 @@ void copy_warning (ToType to, FromType from)
>   	  gcc_assert (supp);
>   
>   	  gcc_checking_assert (nowarn_map);
> -	  nowarn_map->put (to_loc, *from_spec);
> +	  nowarn_spec_t tem = *from_spec;
> +	  nowarn_map->put (to_loc, tem);
>   	}
>         else
>   	{


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] middle-end/101292 - invalid memory access with warning control
  2022-01-17 18:12 ` Martin Sebor
@ 2022-01-18  8:36   ` Richard Biener
  2022-01-18 16:22     ` Martin Sebor
  0 siblings, 1 reply; 5+ messages in thread
From: Richard Biener @ 2022-01-18  8:36 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Mon, 17 Jan 2022, Martin Sebor wrote:

> On 1/17/22 07:32, Richard Biener via Gcc-patches wrote:
> > The warning control falls into the C++ trap of using a reference
> > to old hashtable contents for a put operation which can end up
> > re-allocating that before reading from the old freed referenced to
> > source.  Fixed by introducing a temporary.
> 
> I think a better place to fix this and avoid the gotcha once and
> for all is in the GCC hash_map: C++ containers are expected to
> handle the insertion of own elements gracefully.

I don't think that's reasonably possible if you consider

  T *a = map.get (X);
  T *b = map.get (Y);
  map.put (Z, *a);
  map.put (W, *b);

the only way to "fix" it would be to change the API to not
return by reference for get, remove get_or_insert (or change
its API to also require passing the new value).

Note the above shows that making 'put' take the value by
value instead of by reference doesn't work either.

IMHO the issue is that C++ doesn't make it obvious that 'put'
gets a pointer to the old element (stupid references).

Richard.

> Martin
> 
> > 
> > Bootstrap & regtest running on x86_64-unknown-linux-gnu.
> > 
> > 2022-01-17  Richard Biener  <rguenther@suse.de>
> > 
> >  PR middle-end/101292
> >  * diagnostic-spec.c (copy_warning): Make sure to not
> >  reference old hashtable content on possible resize.
> >  * warning-control.cc (copy_warning): Likewise.
> > ---
> >   gcc/diagnostic-spec.c  | 5 ++++-
> >   gcc/warning-control.cc | 3 ++-
> >   2 files changed, 6 insertions(+), 2 deletions(-)
> > 
> > diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
> > index a8af229d677..4341ccfaae9 100644
> > --- a/gcc/diagnostic-spec.c
> > +++ b/gcc/diagnostic-spec.c
> > @@ -195,7 +195,10 @@ copy_warning (location_t to, location_t from)
> >     else
> >       {
> >         if (from_spec)
> > -	nowarn_map->put (to, *from_spec);
> > +	{
> > +	  nowarn_spec_t tem = *from_spec;
> > +	  nowarn_map->put (to, tem);
> > +	}
> >          else
> >    nowarn_map->remove (to);
> >       }
> > diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
> > index f9808bf4392..fa39ecab421 100644
> > --- a/gcc/warning-control.cc
> > +++ b/gcc/warning-control.cc
> > @@ -206,7 +206,8 @@ void copy_warning (ToType to, FromType from)
> >      gcc_assert (supp);
> >   
> >   	  gcc_checking_assert (nowarn_map);
> > -	  nowarn_map->put (to_loc, *from_spec);
> > +	  nowarn_spec_t tem = *from_spec;
> > +	  nowarn_map->put (to_loc, tem);
> >    }
> >          else
> >    {
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] middle-end/101292 - invalid memory access with warning control
  2022-01-18  8:36   ` Richard Biener
@ 2022-01-18 16:22     ` Martin Sebor
  2022-01-19  7:22       ` Richard Biener
  0 siblings, 1 reply; 5+ messages in thread
From: Martin Sebor @ 2022-01-18 16:22 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches

On 1/18/22 01:36, Richard Biener wrote:
> On Mon, 17 Jan 2022, Martin Sebor wrote:
> 
>> On 1/17/22 07:32, Richard Biener via Gcc-patches wrote:
>>> The warning control falls into the C++ trap of using a reference
>>> to old hashtable contents for a put operation which can end up
>>> re-allocating that before reading from the old freed referenced to
>>> source.  Fixed by introducing a temporary.
>>
>> I think a better place to fix this and avoid the gotcha once and
>> for all is in the GCC hash_map: C++ containers are expected to
>> handle the insertion of own elements gracefully.
> 
> I don't think that's reasonably possible if you consider
> 
>    T *a = map.get (X);
>    T *b = map.get (Y);
>    map.put (Z, *a);
>    map.put (W, *b);

This case is up to the caller to handle, the same as anything else
involving pointers or references into reallocated storage (it's no
different in C than it is in C++).

The specific case I'm referring to is passing a pointer or reference
to a single element in a container to the first modifying call on
the container.

> 
> the only way to "fix" it would be to change the API to not
> return by reference for get, remove get_or_insert (or change
> its API to also require passing the new value).

No, the fix is to have the modifying function create a copy of
the element being inserted before reallocating the container.

> 
> Note the above shows that making 'put' take the value by
> value instead of by reference doesn't work either.
> 
> IMHO the issue is that C++ doesn't make it obvious that 'put'
> gets a pointer to the old element (stupid references).

The problem isn't specific to references, it can come up with
pointers just as easily.  Pointers might just make it more obvious.

Martin

> 
> Richard.
> 
>> Martin
>>
>>>
>>> Bootstrap & regtest running on x86_64-unknown-linux-gnu.
>>>
>>> 2022-01-17  Richard Biener  <rguenther@suse.de>
>>>
>>>   PR middle-end/101292
>>>   * diagnostic-spec.c (copy_warning): Make sure to not
>>>   reference old hashtable content on possible resize.
>>>   * warning-control.cc (copy_warning): Likewise.
>>> ---
>>>    gcc/diagnostic-spec.c  | 5 ++++-
>>>    gcc/warning-control.cc | 3 ++-
>>>    2 files changed, 6 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
>>> index a8af229d677..4341ccfaae9 100644
>>> --- a/gcc/diagnostic-spec.c
>>> +++ b/gcc/diagnostic-spec.c
>>> @@ -195,7 +195,10 @@ copy_warning (location_t to, location_t from)
>>>      else
>>>        {
>>>          if (from_spec)
>>> -	nowarn_map->put (to, *from_spec);
>>> +	{
>>> +	  nowarn_spec_t tem = *from_spec;
>>> +	  nowarn_map->put (to, tem);
>>> +	}
>>>           else
>>>     nowarn_map->remove (to);
>>>        }
>>> diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
>>> index f9808bf4392..fa39ecab421 100644
>>> --- a/gcc/warning-control.cc
>>> +++ b/gcc/warning-control.cc
>>> @@ -206,7 +206,8 @@ void copy_warning (ToType to, FromType from)
>>>       gcc_assert (supp);
>>>    
>>>    	  gcc_checking_assert (nowarn_map);
>>> -	  nowarn_map->put (to_loc, *from_spec);
>>> +	  nowarn_spec_t tem = *from_spec;
>>> +	  nowarn_map->put (to_loc, tem);
>>>     }
>>>           else
>>>     {
>>
>>
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] middle-end/101292 - invalid memory access with warning control
  2022-01-18 16:22     ` Martin Sebor
@ 2022-01-19  7:22       ` Richard Biener
  0 siblings, 0 replies; 5+ messages in thread
From: Richard Biener @ 2022-01-19  7:22 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Tue, 18 Jan 2022, Martin Sebor wrote:

> On 1/18/22 01:36, Richard Biener wrote:
> > On Mon, 17 Jan 2022, Martin Sebor wrote:
> > 
> >> On 1/17/22 07:32, Richard Biener via Gcc-patches wrote:
> >>> The warning control falls into the C++ trap of using a reference
> >>> to old hashtable contents for a put operation which can end up
> >>> re-allocating that before reading from the old freed referenced to
> >>> source.  Fixed by introducing a temporary.
> >>
> >> I think a better place to fix this and avoid the gotcha once and
> >> for all is in the GCC hash_map: C++ containers are expected to
> >> handle the insertion of own elements gracefully.
> > 
> > I don't think that's reasonably possible if you consider
> > 
> >    T *a = map.get (X);
> >    T *b = map.get (Y);
> >    map.put (Z, *a);
> >    map.put (W, *b);
> 
> This case is up to the caller to handle, the same as anything else
> involving pointers or references into reallocated storage (it's no
> different in C than it is in C++).
> 
> The specific case I'm referring to is passing a pointer or reference
> to a single element in a container to the first modifying call on
> the container.

Huh, that's a quite special case I'm not sure "fixing" will avoid
the mistake.

> > 
> > the only way to "fix" it would be to change the API to not
> > return by reference for get, remove get_or_insert (or change
> > its API to also require passing the new value).
> 
> No, the fix is to have the modifying function create a copy of
> the element being inserted before reallocating the container.

Sure, that's possible I guess.

Richard.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-01-19  7:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-17 14:32 [PATCH] middle-end/101292 - invalid memory access with warning control Richard Biener
2022-01-17 18:12 ` Martin Sebor
2022-01-18  8:36   ` Richard Biener
2022-01-18 16:22     ` Martin Sebor
2022-01-19  7:22       ` Richard Biener

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).