[gcc r17-2445] libgomp: Robustify omp_get_device_distances: ... some more [PR125877]

Thomas Schwinge via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:ddf645c09461c6ebf444f27ebbcad8141f0dba56

commit r17-2445-gddf645c09461c6ebf444f27ebbcad8141f0dba56
Author: Thomas Schwinge <[email protected]>
Date:   Wed Jul 15 15:38:08 2026 +0200

    libgomp: Robustify omp_get_device_distances: ... some more [PR125877]
    
    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'.

Diff:
---
 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 85214e56dc41..82711f6e885e 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;
     }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.