Better handling for realpath() failures in windows_make_so() on Cygwin

Message ID 1453305146-7364-1-git-send-email-jon.turney@dronecode.org.uk
State New, archived
Headers

Commit Message

Jon Turney Jan. 20, 2016, 3:52 p.m. UTC
  Fix a memory leak which would occur in the case when the result of realpath() is
greater than or equal to SO_NAME_MAX_PATH_SIZE.

Distinguish between realpath() failing (returning NULL), and returning a path
greather than or equal to SO_NAME_MAX_PATH_SIZE.

Warn rather than stopping with an error in both those cases.

Original patch from Tim Chick.  Memory leak fix by Corinna Vinschen.

See also https://cygwin.com/ml/cygwin/2015-11/msg00353.html

gdb/ChangeLog:

2016-01-20  Jon Turney  <jon.turney@dronecode.org.uk>

	* windows-nat.c (windows_make_so): Fix memory leak when realpath
	returns a path >= SO_NAME_MAX_PATH_SIZE.  Distinguish that case
	from realpath failing.  Warn rather than stopping with an error in
	both cases.
---
 gdb/ChangeLog     |  7 +++++++
 gdb/windows-nat.c | 15 ++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)
  

Comments

Pedro Alves Jan. 20, 2016, 4:19 p.m. UTC | #1
#define SO_NAME_MAX_PATH_SIZE 512       /* FIXME: Should be dynamic */

How about just removing the limit altogether?

Basically, make struct so_list::so_original_name and
struct so_list::so_name pointers instead of arrays?

Thanks,
Pedro Alves
  
Jon Turney March 9, 2016, 5:49 p.m. UTC | #2
On 20/01/2016 16:19, Pedro Alves wrote:
> #define SO_NAME_MAX_PATH_SIZE 512       /* FIXME: Should be dynamic */
>
> How about just removing the limit altogether?
>
> Basically, make struct so_list::so_original_name and
> struct so_list::so_name pointers instead of arrays?

I'm sorry, while that would be nice to have, that's not a project that I 
can take on currently.

In the meantime, please consider approving this patch, or tell me what I 
can do to make it acceptable, since it does fix an actual problem that 
affects some users.
  
Pedro Alves March 9, 2016, 6:09 p.m. UTC | #3
On 03/09/2016 05:49 PM, Jon Turney wrote:
> On 20/01/2016 16:19, Pedro Alves wrote:
>> #define SO_NAME_MAX_PATH_SIZE 512       /* FIXME: Should be dynamic */
>>
>> How about just removing the limit altogether?
>>
>> Basically, make struct so_list::so_original_name and
>> struct so_list::so_name pointers instead of arrays?
> 
> I'm sorry, while that would be nice to have, that's not a project that I 
> can take on currently.
> 
> In the meantime, please consider approving this patch, or tell me what I 
> can do to make it acceptable, since it does fix an actual problem that 
> affects some users.

It's not a big change, I think.  Instead of strcpy'ing strings into
so->so_original_name and so->so_name, we'd just xfree the old
strings and xstrdup new ones.  And then in free_so, we xfree 
so->so_original_name and so->so_name.  All other code that refers to 
so->so_original_name / so->so_name should not need to change, as arrays
decay to pointers anyway.

If you want to avoid convert all targets at once, it's still quite
doable.  Add a new make_so_list() to solib.c that just does:

struct so_list *
make_so_list (void)
{
  struct so_list *new_solib = XCNEW (struct so_list);
  new_solib->so_name = xcalloc (1, SO_NAME_MAX_PATH_SIZE);
  new_solib->so_original_name = xcalloc (1, SO_NAME_MAX_PATH_SIZE);
  return new_solib;
}

and do a trivial replace of these XCNEW/XNEW by a call to make_so_list:

solib-aix.c:      struct so_list *new_solib = XCNEW (struct so_list);
solib-dsbt.c:     sop = XCNEW (struct so_list);
solib-frv.c:      sop = XCNEW (struct so_list);
solib-spu.c:              newobj = XCNEW (struct so_list);
solib-spu.c:      newobj = XCNEW (struct so_list);
solib-svr4.c:  newobj = XCNEW (struct so_list);
solib-svr4.c:  new_elem = XCNEW (struct so_list);
solib-svr4.c:  newobj = XCNEW (struct so_list);
solib-svr4.c:      newobj = XCNEW (struct so_list);
solib-target.c:      new_solib = XCNEW (struct so_list);
windows-nat.c:  so = XCNEW (struct so_list);
solib-svr4.c:      newobj = XNEW (struct so_list);

Then you can adjust the windows-nat.c solib-target.c files (the ones
Windows uses), and leave the rest to someone else (though I imagine 
converting all others would be trivial too).

Once all are converted, we can remove the initial allocations in
make_so_list.

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 71d6670..703b407 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -642,13 +642,22 @@  windows_make_so (const char *name, LPVOID load_addr)
   else
     {
       char *rname = realpath (name, NULL);
-      if (rname && strlen (rname) < SO_NAME_MAX_PATH_SIZE)
+      if (rname)
 	{
-	  strcpy (so->so_name, rname);
+	  if (strlen (rname) < SO_NAME_MAX_PATH_SIZE)
+	    strcpy (so->so_name, rname);
+	  else
+	    {
+	      warning (_("dll path \"%s\" too long"), rname);
+	      strcpy (so->so_name, so->so_original_name);
+	    }
 	  free (rname);
 	}
       else
-	error (_("dll path too long"));
+	{
+	  warning (_("dll path for \"%s\" can not be evaluated"), name);
+	  strcpy (so->so_name, so->so_original_name);
+	}
     }
   /* Record cygwin1.dll .text start/end.  */
   p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);