if (VG_(getegid)() == st.gid)
grpmatch = 1;
else {
- UInt groups[32];
- Int ngrp = VG_(getgroups)(32, groups);
- Int i;
+ UInt *groups = NULL;
+ Int ngrp;
+
+ /* Find out # groups, allocate large enough array and fetch groups */
+ ngrp = VG_(getgroups)(0, NULL);
+ if (ngrp != -1) {
+ groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
+ ngrp = VG_(getgroups)(ngrp, groups);
+ }
+
+ Int i;
/* ngrp will be -1 if VG_(getgroups) failed. */
for (i = 0; i < ngrp; i++) {
if (groups[i] == st.gid) {
break;
}
}
+ VG_(free)(groups);
}
if (grpmatch) {
/* Get supplementary groups into list[0 .. size-1]. Returns the
number of groups written, or -1 if error. Note that in order to be
portable, the groups are 32-bit unsigned ints regardless of the
- platform. */
+ platform.
+ As a special case, if size == 0 the function returns the number of
+ groups leaving list untouched. */
Int VG_(getgroups)( Int size, UInt* list )
{
+ if (size < 0) return -1;
+
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
|| defined(VGP_mips64_linux)
Int i;
SysRes sres;
- UShort list16[64];
- if (size < 0) return -1;
- if (size > 64) size = 64;
+ UShort list16[size];
sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16);
if (sr_isError(sres))
return -1;
- if (sr_Res(sres) > size)
- return -1;
- for (i = 0; i < sr_Res(sres); i++)
- list[i] = (UInt)list16[i];
+ if (size != 0) {
+ for (i = 0; i < sr_Res(sres); i++)
+ list[i] = (UInt)list16[i];
+ }
return sr_Res(sres);
# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \