Per commit 929b1c42f3d23dcffacdedb005ab83d3607b47ce
"libgomp: Robustify omp_get_device_distances [PR125877]", we've got:

    [...]
      FILE *f = fopen ("/sys/devices/system/node/online", "r");
      if (f == NULL)
        goto fail;
      char *lineptr = NULL;
    [...]
    fail:
      free (lineptr);
    [...]

In C (per my understanding), this is "valid" (syntax): 'lineptr' appears as
part of the block it's declared in.  However, it only gets initialized (to
'NULL') only *after* the first 'goto fail;', therefore that 'goto fail;',
'free (lineptr);' code path invokes undefined behavior, crashes for random junk
in 'lineptr'.

We've got:

    [...]
      char *lineptr = NULL;
      size_t nline;
      if (getline (&lineptr, &nline, f) <= 0)
    [...]

Per the glibc manual ('info libc getline'):

|  -- Function: ssize_t getline (char **LINEPTR, size_t *N, FILE *STREAM)
| [...]
|      If you set ‘*LINEPTR’ to a null pointer, and ‘*N’ to zero, before
|      the call, then ‘getline’ allocates the initial buffer [...]

Confusingly, that's slightly different from the 'getline' definition in
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/getline.html> as
well as common implementation (including glibc's...), which don't require
zero-initialiation of 'nline' given NULL for 'lineptr'.  We shall err on the
side of caution, and do similar to other libgomp 'getline' code, that is,
initialize 'nline' to zero in this case here.

We've got:

    [...]
      if (getline (&lineptr, &nline, f) <= 0)
        {
          free (lineptr);
          fclose (f);
          goto fail;
        }
    [...]
    fail:
      free (lineptr);
    [...]

..., that is, a double 'free' in the error case.

        PR libgomp/125877
        libgomp/
        * config/linux/numa.c (gomp_get_numa_distance): Move 'lineptr'
        initialization earlier, robustify 'getline' call, avoid double
        'free'.
---
 libgomp/config/linux/numa.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/libgomp/config/linux/numa.c b/libgomp/config/linux/numa.c
index 85214e56dc4..82711f6e885 100644
--- a/libgomp/config/linux/numa.c
+++ b/libgomp/config/linux/numa.c
@@ -87,14 +87,13 @@ retry:
   /* Obtain numa nodes.  */
 
   num = 0;
+  char *lineptr = NULL;
+  size_t nline = 0;
   FILE *f = fopen ("/sys/devices/system/node/online", "r");
   if (f == NULL)
     goto fail;
-  char *lineptr = NULL;
-  size_t nline;
   if (getline (&lineptr, &nline, f) <= 0)
     {
-      free (lineptr);
       fclose (f);
       goto fail;
     }
-- 
2.53.0

Reply via email to