Re: getpwent_r(3) needs gr->gr_mem to be freed, but that's not documented
From: Alejandro Colomar <alx@kernel.org>
Date: 2025-09-29 01:22:25
On Mon, Sep 29, 2025 at 01:00:06AM +0200, Alejandro Colomar wrote:
So far, I've written this:
[...]
I've applied some fixes to make sure that alignment is valid. Now,
gr_mem comes first in the buffer (which also allows freeing it more
easily), and I added an explicit check about the alignment.
// from-string get group entry
struct group *
sgetgrent(const char *s)
{
int e;
size_t n, lssize, size;
static char *buf = NULL;
static struct group grent = {};
n = strchrcnt(s, ',') + 2;
lssize = n * sizeof(char *); // For 'grent.gr_mem'.
size = lssize + strlen(s) + 1;
free(buf);
buf = MALLOC(size, char);
if (buf == NULL)
return NULL;
e = sgetgrent_r(s, &grent, buf, size);
if (e != 0) {
errno = e;
return NULL;
}
return &grent;
}
// from-string get group entry re-entrant
int
sgetgrent_r(size_t size;
const char *restrict s, struct group *restrict grent,
char buf[restrict size], size_t size)
{
char *p, *end;
char *fields[4];
size_t n, lssize;
if (!is_aligned(buf, char *))
return EINVAL;
grent->gr_mem = (char **) buf;
// The first 'lssize' bytes of 'buf' are used for 'grent->gr_mem'.
n = strchrcnt(s, ',') + 2;
lssize = n * sizeof(char *);
if (lssize >= size)
return E2BIG;
// The remaining bytes of 'buf' are used for a copy of 's'.
end = buf + size;
p = buf + lssize;
if (stpecpy(p, end, s) == NULL)
return errno;
stpsep(p, "\n");
if (STRSEP2ARR(p, ":", fields) == -1)
return EINVAL;
grent->gr_name = fields[0];
grent->gr_passwd = fields[1];
if (get_gid(fields[2], &grent->gr_gid) == -1)
return errno;
if (csv2ls(fields[3], n, grent->gr_mem) == -1)
return errno;
return 0;
}
Cheers,
Alex
--
<https://www.alejandro-colomar.es>
Use port 80 (that is, <...:80/>). Attachments
- signature.asc [application/pgp-signature] 833 bytes