From: Bruno Haible <bruno@clisp.org>
To: musl@lists.openwall.com
Cc: bug-gnulib@gnu.org
Subject: test-getopt-posix fails on musl
Date: Sat, 24 Feb 2018 10:31:55 +0100 [thread overview]
Message-ID: <1714550.SfedhZ9LKS@omega> (raw)
[-- Attachment #1: Type: text/plain, Size: 416 bytes --]
Hi,
On Alpine Linux 3.7.0, which uses musl libc, the gnulib test 'test-getopt-posix'
fails. To me, this looks like a POSIX compliance bug of musl.
Find attached a reduced test case.
$ gcc foo.c -Wall
$ ./a.ou t
foo.c:134: assertion 'options[0] == ':' || ((options[0] == '-' || options[0] == '+') && options[1] == ':')' failed
Reference: POSIX
http://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
[-- Attachment #2: foo.c --]
[-- Type: text/x-csrc, Size: 5278 bytes --]
/* POSIX and glibc provide the getopt() function in <unistd.h>, see
http://pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html
https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html
But gnulib provides the getopt() function in <getopt.h>, not in <unistd.h>.
Nevertheless the getopt() function should also be found in <unistd.h>. */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define TEST_GETOPT_TMP_NAME "test-getopt-posix.tmp"
/* This test intentionally remaps stderr. So, we arrange to have fd 10
(outside the range of interesting fd's during the test) set up to
duplicate the original stderr. */
#define BACKUP_STDERR_FILENO 10
#define ASSERT_STREAM myerr
#ifndef FALLTHROUGH
# if __GNUC__ < 7
# define FALLTHROUGH ((void) 0)
# else
# define FALLTHROUGH __attribute__ ((__fallthrough__))
# endif
#endif
/* Define ASSERT_STREAM before including this file if ASSERT must
target a stream other than stderr. */
#ifndef ASSERT_STREAM
# define ASSERT_STREAM stderr
#endif
/* ASSERT (condition);
verifies that the specified condition is fulfilled. If not, a message
is printed to ASSERT_STREAM if defined (defaulting to stderr if
undefined) and the program is terminated with an error code.
This macro has the following properties:
- The programmer specifies the expected condition, not the failure
condition. This simplifies thinking.
- The condition is tested always, regardless of compilation flags.
(Unlike the macro from <assert.h>.)
- On Unix platforms, the tester can debug the test program with a
debugger (provided core dumps are enabled: "ulimit -c unlimited").
- For the sake of platforms where no debugger is available (such as
some mingw systems), an error message is printed on the error
stream that includes the source location of the ASSERT invocation.
*/
#define ASSERT(expr) \
do \
{ \
if (!(expr)) \
{ \
fprintf (ASSERT_STREAM, "%s:%d: assertion '%s' failed\n", \
__FILE__, __LINE__, #expr); \
fflush (ASSERT_STREAM); \
abort (); \
} \
} \
while (0)
static FILE *myerr;
int
main (void)
{
/* This test validates that stderr is used correctly, so move the
original into fd 10. */
if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
|| (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
return 2;
ASSERT (freopen (TEST_GETOPT_TMP_NAME, "w", stderr) == stderr);
/* These default values are required by POSIX. */
ASSERT (optind == 1);
ASSERT (opterr != 0);
setenv ("POSIXLY_CORRECT", "1", 1);
int start = 1;
{
int a_seen = 0;
int b_seen = 0;
const char *p_value = NULL;
const char *q_value = NULL;
int non_options_count = 0;
int unrecognized = 0;
bool output;
int argc = 0;
const char *argv[10];
argv[argc++] = "program";
argv[argc++] = "-p";
argv[argc++] = "foo";
argv[argc++] = "-:";
argv[argc++] = "-a";
argv[argc++] = "bar";
argv[argc] = NULL;
optind = start;
opterr = 42;
{
const char *options = "abp:q:";
int c;
int pos = ftell (stderr);
while ((c = getopt (argc, (char **) argv, options)) != -1)
{
switch (c)
{
case 'a':
a_seen++;
break;
case 'b':
b_seen++;
break;
case 'p':
p_value = optarg;
break;
case 'q':
q_value = optarg;
break;
case '\1':
/* Must only happen with option '-' at the beginning. */
ASSERT (options[0] == '-');
non_options_count++;
break;
case ':':
/* Must only happen with option ':' at the beginning. */
ASSERT (options[0] == ':'
|| ((options[0] == '-' || options[0] == '+')
&& options[1] == ':'));
FALLTHROUGH;
case '?':
unrecognized = optopt;
break;
default:
unrecognized = c;
break;
}
}
output = pos < ftell (stderr);
}
ASSERT (a_seen == 1);
ASSERT (b_seen == 0);
ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
ASSERT (q_value == NULL);
ASSERT (non_options_count == 0);
ASSERT (unrecognized == ':');
ASSERT (optind == 5);
ASSERT (output);
}
ASSERT (fclose (stderr) == 0);
ASSERT (remove (TEST_GETOPT_TMP_NAME) == 0);
return 0;
}
next reply other threads:[~2018-02-24 9:31 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-24 9:31 Bruno Haible [this message]
2018-02-24 15:09 ` Rich Felker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1714550.SfedhZ9LKS@omega \
--to=bruno@clisp.org \
--cc=bug-gnulib@gnu.org \
--cc=musl@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).