--- src/osdep_darwin.c.orig 2019-02-16 00:34:26.000000000 +0100 +++ src/osdep_darwin.c 2020-10-19 19:23:38.000000000 +0200 @@ -1,4 +1,3 @@ - #include #include @@ -23,8 +22,8 @@ Bool GetCommandForPid(int pid, char ***argv, int *argc) #ifdef KERN_PROCARGS2 { - int j, mib[4]; - unsigned int i, idx; + int mib[4]; + unsigned int idx; size_t count; static char *args = NULL; static int argmax = 0; @@ -70,21 +69,46 @@ idx++; /* args[idx] is at at begininng of args now */ - *argv = (char **)wmalloc(sizeof(char *) * (*argc + 1 /* term. null ptr */)); - (*argv)[0] = args + idx; - - /* go through args, set argv[$next] to the beginning of each string */ - for (i = 0, j = 1; i < count - idx /* do not overrun */; i++) { - if (args[idx + i] != '\0') - continue; - if (args[idx + i] == '\0') - (*argv)[j++] = &args[idx + i + 1]; - if (j == *argc) - break; - } - - /* the list of arguments must be terminated by a null pointer */ - (*argv)[j] = NULL; + int found = 0; + char *p = &args[idx]; + while(found < *argc) + { + while(*p != '\0') p++; // look for the next \0 + while(*p == '\0') p++; // skip over padding \0s + found++; + + // Don’t overrun! + if (p-args >= argmax) + { + return False; + } + } + // At this point, p points to the last \0 in the source array. + + // Buffer needed for the strings + unsigned stringbuf_size = p - &args[idx]; + + // Buffer needed for the pointers (plus one terminating NULL) + unsigned pointerbuf_size = sizeof(char *) * (*argc + 1); + + *argv = wmalloc(pointerbuf_size + stringbuf_size); + char* stringstart = (char *)(*argv) + pointerbuf_size; + + memcpy(stringstart, &args[idx], stringbuf_size); + + found = 0; + p = stringstart; + while(found < *argc) + { + (*argv)[found] = p; + + while(*p != '\0') p++; // look for the next \0 + while(*p == '\0') p++; // skip over padding \0s + + found++; + } + (*argv)[found] = NULL; // Terminating NULL + return True; } #else /* !KERN_PROCARGS2 */