mailing list of musl libc
 help / color / mirror / code / Atom feed
* test-getopt-posix fails on musl
@ 2018-02-24  9:31 Bruno Haible
  2018-02-24 15:09 ` Rich Felker
  0 siblings, 1 reply; 2+ messages in thread
From: Bruno Haible @ 2018-02-24  9:31 UTC (permalink / raw)
  To: musl; +Cc: bug-gnulib

[-- 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;
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-02-24 15:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-24  9:31 test-getopt-posix fails on musl Bruno Haible
2018-02-24 15:09 ` Rich Felker

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).