https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125877

--- Comment #9 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Thomas Schwinge <[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'.

Reply via email to