libs/libc/grp: fix getgrbuf_r() pointer-alignment padding

padlen = sizeof(void *) - (addr % sizeof(void *)) never returns 0, even
when addr is already pointer-aligned -- it returns a full alignment unit
instead. Since callers size buflen for zero padding, the subsequent
"buflen < padlen + reqdlen" check then always fails, so getgrgid()/
getgrnam() and their _r variants always return ERANGE.

Found via `id` on sim:toybox, which resolves gid 0 to "root" through
this path.

Signed-off-by: Alan C. Assis <acassis@gmail.com>
Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Alan Carvalho de Assis 2026-07-28 04:07:16 -03:00 committed by Xiang Xiao
parent 198747322c
commit 3635004dcd

View file

@ -77,7 +77,15 @@ int getgrbuf_r(gid_t gid, FAR const char *name, FAR const char *passwd,
namesize = strlen(name) + 1;
passwdsize = strlen(passwd) + 1;
padlen = sizeof(FAR void *) - ((uintptr_t)buf % sizeof(FAR char *));
/* Bytes needed to round 'buf' up to the next pointer-aligned address.
* The two's-complement modulo trick below yields 0 when 'buf' is
* already aligned; "sizeof(void *) - (addr % sizeof(void *))" (the
* previous formula) does not, always returning a full alignment unit
* in that case, which made the buflen check below always fail.
*/
padlen = (-(uintptr_t)buf) % sizeof(FAR void *);
reqdlen = sizeof(FAR void *) + namesize + passwdsize;
if (buflen < padlen + reqdlen)