public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust
@ 2016-06-09 16:34 Tom Tromey
  2016-06-28 10:43 ` Yao Qi
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2016-06-09 16:34 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

PR gdb/17210 concerns a possible memory leak in read_memory_robust.
The bug can happen because read_memory_robust allocates memory, does
not install any cleanups, and invokes QUIT.  Similarly, it target_read
calls QUIT, so it too can potentially throw.

The fix is to install cleanups to guard the allocated memory.

Built and regtested on x86-64 Fedora 23.  I couldn't think of a way to
test this, so no new test; and of course this means it should have
more careful review.

2016-06-09  Tom Tromey  <tom@tromey.com>

	PR gdb/17210:
	* target.c (free_memory_read_result_vector): Take a pointer to the
	VEC as an argument.
	(read_memory_robust): Install a cleanup for "result".
	* mi/mi-main.c (mi_cmd_data_read_memory_bytes): Update.
---
 gdb/ChangeLog    |  8 ++++++++
 gdb/mi/mi-main.c |  2 +-
 gdb/target.c     | 15 +++++++++++----
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9c09269..dc1c908 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-06-09  Tom Tromey  <tom@tromey.com>
+
+	PR gdb/17210:
+	* target.c (free_memory_read_result_vector): Take a pointer to the
+	VEC as an argument.
+	(read_memory_robust): Install a cleanup for "result".
+	* mi/mi-main.c (mi_cmd_data_read_memory_bytes): Update.
+
 2016-06-07  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* mi/mi-interp.c (mi_record_changed): Add missing braces.
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index d53bcc7..0e048f3 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -1635,7 +1635,7 @@ mi_cmd_data_read_memory_bytes (char *command, char **argv, int argc)
 
   result = read_memory_robust (current_target.beneath, addr, length);
 
-  cleanups = make_cleanup (free_memory_read_result_vector, result);
+  cleanups = make_cleanup (free_memory_read_result_vector, &result);
 
   if (VEC_length (memory_read_result_s, result) == 0)
     error (_("Unable to read memory."));
diff --git a/gdb/target.c b/gdb/target.c
index c0ce46d..442d632 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -1793,15 +1793,15 @@ read_whatever_is_readable (struct target_ops *ops,
 void
 free_memory_read_result_vector (void *x)
 {
-  VEC(memory_read_result_s) *v = (VEC(memory_read_result_s) *) x;
+  VEC(memory_read_result_s) **v = (VEC(memory_read_result_s) **) x;
   memory_read_result_s *current;
   int ix;
 
-  for (ix = 0; VEC_iterate (memory_read_result_s, v, ix, current); ++ix)
+  for (ix = 0; VEC_iterate (memory_read_result_s, *v, ix, current); ++ix)
     {
       xfree (current->data);
     }
-  VEC_free (memory_read_result_s, v);
+  VEC_free (memory_read_result_s, *v);
 }
 
 VEC(memory_read_result_s) *
@@ -1810,6 +1810,8 @@ read_memory_robust (struct target_ops *ops,
 {
   VEC(memory_read_result_s) *result = 0;
   int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
+  struct cleanup *cleanup = make_cleanup (free_memory_read_result_vector,
+					  &result);
 
   LONGEST xfered_total = 0;
   while (xfered_total < len)
@@ -1836,6 +1838,7 @@ read_memory_robust (struct target_ops *ops,
 	{
 	  LONGEST to_read = min (len - xfered_total, region_len);
 	  gdb_byte *buffer = (gdb_byte *) xmalloc (to_read * unit_size);
+	  struct cleanup *inner_cleanup = make_cleanup (xfree, buffer);
 
 	  LONGEST xfered_partial =
 	      target_read (ops, TARGET_OBJECT_MEMORY, NULL,
@@ -1846,7 +1849,7 @@ read_memory_robust (struct target_ops *ops,
 	    {
 	      /* Got an error reading full chunk.  See if maybe we can read
 		 some subrange.  */
-	      xfree (buffer);
+	      do_cleanups (inner_cleanup);
 	      read_whatever_is_readable (ops, offset + xfered_total,
 					 offset + xfered_total + to_read,
 					 unit_size, &result);
@@ -1855,6 +1858,8 @@ read_memory_robust (struct target_ops *ops,
 	  else
 	    {
 	      struct memory_read_result r;
+
+	      discard_cleanups (inner_cleanup);
 	      r.data = buffer;
 	      r.begin = offset + xfered_total;
 	      r.end = r.begin + xfered_partial;
@@ -1864,6 +1869,8 @@ read_memory_robust (struct target_ops *ops,
 	  QUIT;
 	}
     }
+
+  discard_cleanups (cleanup);
   return result;
 }
 
-- 
2.5.5

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

* Re: [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust
  2016-06-09 16:34 [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust Tom Tromey
@ 2016-06-28 10:43 ` Yao Qi
  2016-06-28 14:40   ` Tom Tromey
  2016-06-28 17:48   ` Pedro Alves
  0 siblings, 2 replies; 5+ messages in thread
From: Yao Qi @ 2016-06-28 10:43 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Thu, Jun 9, 2016 at 5:33 PM, Tom Tromey <tom@tromey.com> wrote:
>
>  VEC(memory_read_result_s) *
> @@ -1810,6 +1810,8 @@ read_memory_robust (struct target_ops *ops,
>  {
>    VEC(memory_read_result_s) *result = 0;
>    int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
> +  struct cleanup *cleanup = make_cleanup (free_memory_read_result_vector,
> +                                         &result);
>

result is a local variable on stack, so its address is meaningless when the
exception is throw, because the stack has already been destroyed.

Probably, we can register cleanup for result once it becomes to non-NULL,
and changes in free_memory_read_result_vector are not needed.

-- 
Yao (齐尧)

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

* Re: [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust
  2016-06-28 10:43 ` Yao Qi
@ 2016-06-28 14:40   ` Tom Tromey
  2016-06-28 17:48   ` Pedro Alves
  1 sibling, 0 replies; 5+ messages in thread
From: Tom Tromey @ 2016-06-28 14:40 UTC (permalink / raw)
  To: Yao Qi; +Cc: Tom Tromey, gdb-patches

>>>>> "Yao" == Yao Qi <qiyaoltc@gmail.com> writes:

Yao> On Thu, Jun 9, 2016 at 5:33 PM, Tom Tromey <tom@tromey.com> wrote:
>> 
>> VEC(memory_read_result_s) *
>> @@ -1810,6 +1810,8 @@ read_memory_robust (struct target_ops *ops,
>> {
>> VEC(memory_read_result_s) *result = 0;
>> int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
>> +  struct cleanup *cleanup = make_cleanup (free_memory_read_result_vector,
>> +                                         &result);
>> 

Yao> result is a local variable on stack, so its address is meaningless when the
Yao> exception is throw, because the stack has already been destroyed.

Yao> Probably, we can register cleanup for result once it becomes to non-NULL,
Yao> and changes in free_memory_read_result_vector are not needed.

I don't think that will work, because resizing the vector may cause the
value to change.  Though one option would be to discard the cleanup and
recreate it after each push.

Tom

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

* Re: [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust
  2016-06-28 10:43 ` Yao Qi
  2016-06-28 14:40   ` Tom Tromey
@ 2016-06-28 17:48   ` Pedro Alves
  2016-06-29  9:27     ` Yao Qi
  1 sibling, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2016-06-28 17:48 UTC (permalink / raw)
  To: Yao Qi, Tom Tromey; +Cc: gdb-patches

On 06/28/2016 11:42 AM, Yao Qi wrote:
> On Thu, Jun 9, 2016 at 5:33 PM, Tom Tromey <tom@tromey.com> wrote:
>>
>>  VEC(memory_read_result_s) *
>> @@ -1810,6 +1810,8 @@ read_memory_robust (struct target_ops *ops,
>>  {
>>    VEC(memory_read_result_s) *result = 0;
>>    int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
>> +  struct cleanup *cleanup = make_cleanup (free_memory_read_result_vector,
>> +                                         &result);
>>
> 
> result is a local variable on stack, so its address is meaningless when the
> exception is throw, because the stack has already been destroyed.

Can you clarify?
Cleanups do run before the stack is destroyed.  See most 
free_current_contents users.

Thanks,
Pedro Alves

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

* Re: [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust
  2016-06-28 17:48   ` Pedro Alves
@ 2016-06-29  9:27     ` Yao Qi
  0 siblings, 0 replies; 5+ messages in thread
From: Yao Qi @ 2016-06-29  9:27 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

On Tue, Jun 28, 2016 at 6:47 PM, Pedro Alves <palves@redhat.com> wrote:
> On 06/28/2016 11:42 AM, Yao Qi wrote:
>> On Thu, Jun 9, 2016 at 5:33 PM, Tom Tromey <tom@tromey.com> wrote:
>>>
>>>  VEC(memory_read_result_s) *
>>> @@ -1810,6 +1810,8 @@ read_memory_robust (struct target_ops *ops,
>>>  {
>>>    VEC(memory_read_result_s) *result = 0;
>>>    int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
>>> +  struct cleanup *cleanup = make_cleanup (free_memory_read_result_vector,
>>> +                                         &result);
>>>
>>
>> result is a local variable on stack, so its address is meaningless when the
>> exception is throw, because the stack has already been destroyed.
>
> Can you clarify?
> Cleanups do run before the stack is destroyed.  See most
> free_current_contents users.

Urr.. right... do_cleanups is called when the exception is thrown
where the stack
is not destroyed yet.  I thought do_cleanups is called when gdb goes back to
the top level in this case.

Tom, the patch is good to me then.

-- 
Yao (齐尧)

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

end of thread, other threads:[~2016-06-29  9:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-09 16:34 [RFA] PR gdb/17210 - fix possible memory leak in read_memory_robust Tom Tromey
2016-06-28 10:43 ` Yao Qi
2016-06-28 14:40   ` Tom Tromey
2016-06-28 17:48   ` Pedro Alves
2016-06-29  9:27     ` Yao Qi

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