diff --color -ru a/libcap/_makenames.c b/libcap/_makenames.c --- a/libcap/_makenames.c 2022-01-28 14:41:38.357147972 +0100 +++ b/libcap/_makenames.c 2022-01-28 14:42:45.681379827 +0100 @@ -45,7 +45,7 @@ if (maxcaps <= list[i].index) { maxcaps = list[i].index + 1; } - if (list[i].index >= pointers_avail) { + if (pointers == NULL || list[i].index >= pointers_avail) { int was = pointers_avail * sizeof(char *); pointers_avail = 2 * list[i].index + 1; pointers = recalloc(pointers, was, pointers_avail * sizeof(char *)); diff --color -ru a/progs/capsh.c b/progs/capsh.c --- a/progs/capsh.c 2022-01-28 14:41:38.359148009 +0100 +++ b/progs/capsh.c 2022-01-28 14:42:45.682379846 +0100 @@ -34,6 +34,35 @@ #define MAX_GROUPS 100 /* max number of supplementary groups for user */ +/* parse a non-negative integer with some error handling */ +static unsigned long nonneg_uint(const char *text, const char *prefix, int *ok) +{ + char *remains; + unsigned long value; + ssize_t len = strlen(text); + + if (len == 0 || *text == '-') { + goto fail; + } + value = strtoul(text, &remains, 0); + if (*remains) { + goto fail; + } + if (ok != NULL) { + *ok = 1; + } + return value; + +fail: + if (ok == NULL) { + fprintf(stderr, "%s: want non-negative integer, got \"%s\"\n", + prefix, text); + exit(1); + } + *ok = 0; + return 0; +} + static char *binary(unsigned long value) { static char string[8*sizeof(unsigned long) + 1]; @@ -362,7 +391,7 @@ parts = strdup(path); if (parts == NULL) { - fprintf(stderr, "insufficient memory for parts of path\n"); + fprintf(stderr, "insufficient memory for parts of path\n"); exit(1); } @@ -610,7 +639,7 @@ unsigned value; int set; - value = strtoul(argv[i]+7, NULL, 0); + value = nonneg_uint(argv[i]+7, "invalid --keep value", NULL); set = prctl(PR_SET_KEEPCAPS, value); if (set < 0) { fprintf(stderr, "prctl(PR_SET_KEEPCAPS, %u) failed: %s\n", @@ -667,7 +696,7 @@ } else if (!strncmp("--secbits=", argv[i], 10)) { unsigned value; int status; - value = strtoul(argv[i]+10, NULL, 0); + value = nonneg_uint(argv[i]+10, "invalid --secbits value", NULL); status = cap_set_secbits(value); if (status < 0) { fprintf(stderr, "failed to set securebits to 0%o/0x%x\n", @@ -680,7 +709,7 @@ fprintf(stderr, "already forked\n"); exit(1); } - value = strtoul(argv[i]+10, NULL, 0); + value = nonneg_uint(argv[i]+10, "invalid --forkfor value", NULL); if (value == 0) { goto usage; } @@ -696,7 +725,8 @@ pid_t result; unsigned value; - value = strtoul(argv[i]+9, NULL, 0); + value = nonneg_uint(argv[i]+9, "invalid --killit signo value", + NULL); if (!child) { fprintf(stderr, "no forked process to kill\n"); exit(1); @@ -722,7 +752,7 @@ unsigned value; int status; - value = strtoul(argv[i]+6, NULL, 0); + value = nonneg_uint(argv[i]+6, "invalid --uid value", NULL); status = setuid(value); if (status < 0) { fprintf(stderr, "Failed to set uid=%u: %s\n", @@ -733,7 +763,7 @@ unsigned value; int status; - value = strtoul(argv[i]+10, NULL, 0); + value = nonneg_uint(argv[i]+10, "invalid --cap-uid value", NULL); status = cap_setuid(value); if (status < 0) { fprintf(stderr, "Failed to cap_setuid(%u): %s\n", @@ -744,7 +774,7 @@ unsigned value; int status; - value = strtoul(argv[i]+6, NULL, 0); + value = nonneg_uint(argv[i]+6, "invalid --gid value", NULL); status = setgid(value); if (status < 0) { fprintf(stderr, "Failed to set gid=%u: %s\n", @@ -924,7 +954,7 @@ } else if (!strncmp("--is-uid=", argv[i], 9)) { unsigned value; uid_t uid; - value = strtoul(argv[i]+9, NULL, 0); + value = nonneg_uint(argv[i]+9, "invalid --is-uid value", NULL); uid = getuid(); if (uid != value) { fprintf(stderr, "uid: got=%d, want=%d\n", uid, value); @@ -933,7 +963,7 @@ } else if (!strncmp("--is-gid=", argv[i], 9)) { unsigned value; gid_t gid; - value = strtoul(argv[i]+9, NULL, 0); + value = nonneg_uint(argv[i]+9, "invalid --is-gid value", NULL); gid = getgid(); if (gid != value) { fprintf(stderr, "gid: got=%d, want=%d\n", gid, value); diff --color -ru a/tests/libcap_psx_test.c b/tests/libcap_psx_test.c --- a/tests/libcap_psx_test.c 2022-01-28 14:41:38.360148027 +0100 +++ b/tests/libcap_psx_test.c 2022-01-28 14:42:45.683379864 +0100 @@ -21,7 +21,10 @@ exit(1); } if (pid == 0) { - cap_set_proc(start); + if (cap_set_proc(start)) { + perror("setting empty caps failed"); + exit(1); + } exit(0); } int res; @@ -51,7 +54,10 @@ for (i = 0; i < 10; i++) { printf("."); /* because of fork, this may print double */ fflush(stdout); /* try to limit the above effect */ - cap_set_proc(start); + if (cap_set_proc(start)) { + perror("failed to set proc"); + exit(1); + } usleep(1000); } printf(" PASSED\n");