|
Message-ID: <4c82138762e69f64a1f95639090edbd8@ispras.ru> Date: Thu, 25 May 2023 10:53:09 +0300 From: Alexey Izbyshev <izbyshev@...ras.ru> To: musl@...ts.openwall.com Subject: getopt_long() can corrupt argv when an argument for a short option is missing POSIX requires getopt() to set optind to argc + 1 in case of a missing argument[1], and musl follows it. This bites getopt_long() (which reuses getopt()) in two ways: * getopt_long() moves argv[optind - 1] (NULL) when permuting argv to make all options precede other arguments, essentially corrupting argv. * even when permuting is not required, getopt_long() is both incompatible with glibc (which doesn't increment optind past NULL) and inconsistent with itself (for a long option with a missing argument, musl doesn't increment optind past NULL too). Example of the wrong NULL shifting: #include <getopt.h> #include <stdio.h> int main(int argc, char *argv[]) { for (int i = 0; i < 2; i++) { int r = getopt_long(argc, argv, "o:", NULL, NULL); printf("r: %d\n", r); printf("optind: %d\n", optind); for (int i = 0; i <= argc; i++) printf("%d: '%s'\n", i, argv[i]); } } With glibc: $ ./a.out arg -o ./a.out: option requires an argument -- 'o' r: 63 optind: 3 0: './a.out' 1: 'arg' 2: '-o' 3: '(null)' r: -1 optind: 2 0: './a.out' 1: '-o' 2: 'arg' 3: '(null)' (Note that glibc permutes argv *before* parsing then next option, and even before comparing optind and argc, so argv is still permuted on the second invocation.) With musl: $ ./a.out arg -o ./a.out: option requires an argument: o r: 63 optind: 3 0: './a.out' 1: '-o' 2: '(null)' 3: 'arg' r: -1 optind: 3 0: './a.out' 1: '-o' 2: '(null)' 3: 'arg' Maybe we could just skip permuting and adjust optind if we detected a missing argument? resumed = optind; ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly); + if (optind > argc) + return optind--, ret; if (resumed > skipped) { On a subsequent invocation we won't permute, unlike glibc, but maybe this is a good thing, given that such permutation makes it look like there is no missing argument, essentially changing the command semantics. Alexey [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.