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)
[...]
The 'getline' API states:
| -- 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 [...]
..., so we should initialize 'nline' to zero.
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, fix '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 85214e56dc41..e092f398540f 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;
FILE *f = fopen ("/sys/devices/system/node/online", "r");
if (f == NULL)
goto fail;
- char *lineptr = NULL;
- size_t nline;
+ size_t nline = 0;
if (getline (&lineptr, &nline, f) <= 0)
{
- free (lineptr);
fclose (f);
goto fail;
}
--
2.34.1