[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#969618: getopt: optarg is NULL outside of loop



Package: libc6
Version: 2.31-3
Severity: normal
X-Debbugs-Cc: 

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

I suspect this is an upstream problem but I'm reporting it here
first per their policy [1] since I'm unsure.

Both POSIX (including the Issue 8 draft) and the GNU C Library
manual say that when an argument is provided for an option, a
pointer to it is provided as optarg.

It seems like after leaving the while() loop getopt is usually
used in, optarg points to NULL instead, even if no other options,
bearing arguments or not, are used. It's a little grey but POSIX
doesn't seem to permit this, and the (non-DFSG) glibc manual could
be construed as saying it should work fine this way:
> If the option has an argument, getopt returns the argument by storing
> it in the variable optarg. You don’t ordinarily need to copy the optarg
> string, since it is a pointer into the original argv array, not into a
> static area that might be overwritten. 

Everything works fine with Musl libc which can be tried with musl-gcc.
Consider this example program:

#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
	int opt;
	while((opt = getopt(argc, argv, "a:")) != -1) {}
	assert(optarg != NULL);
}

If this is invoked as './a.out -afoo', the inner assertion will
the last assertion will fail with glibc. In the absence of
a compelling reason (such as if I were using the GNU extension of
having an optional argument via '::'), standards aside, it would
be helpful for me if the variable could be left alone.

[1] https://sourceware.org/glibc/wiki/FilingBugs
[2] https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html
- -- System Information:
Debian Release: bullseye/sid
  APT prefers testing
  APT policy: (500, 'testing'), (2, 'unstable'), (1, 'testing-debug'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.7.0-3-amd64 (SMP w/2 CPU threads)
Kernel taint flags: TAINT_USER, TAINT_FIRMWARE_WORKAROUND
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages libc6 depends on:
ii  libcrypt1  1:4.4.17-1
ii  libgcc-s1  10.2.0-5

Versions of packages libc6 recommends:
ii  libidn2-0  2.3.0-1

Versions of packages libc6 suggests:
ii  debconf [debconf-2.0]  1.5.74
ii  glibc-doc              2.31-3
ii  libc-l10n              2.31-3
ii  locales                2.31-3

- -- debconf information:
  glibc/restart-failed:
  glibc/upgrade: true
  glibc/kernel-too-old:
  glibc/kernel-not-supported:
* libraries/restart-without-asking: true
  glibc/disable-screensaver:
  glibc/restart-services:

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQT287WtmxUhmhucNnhyvHFIwKstpwUCX1Q6TgAKCRByvHFIwKst
p+D0AQDqLFwxGh/oTV+13E5stB3WvG9zD0tpMiol/xHW0QuERgEAsPKsGbQBW2nG
VFzkfExA5cGyGj0GW7IyKg42+wLaZgI=
=WQf5
-----END PGP SIGNATURE-----

Reply to: