Possible bug in argp

Guangxin Yang <[email protected]> Sat, 07 Aug 2021 18:29:22 +0800
Newsgroups gmane.comp.gnu.utils.bugs
Message-ID <[email protected]>
------=_Part_36933_740982792.1628332162750
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hello there,=C2=A0



There may be a bug on macOS when calling arpg_help() with options having a =
non-NULL arg value in the argp_option.=C2=A0



For the example=C2=A0https://www.gnu.org/software/libc/manual/html_node/Arg=
p-Example-3.html, I added a case like this:=C2=A0




=C2=A0 =C2=A0 case ARGP_KEY_NO_ARGS:

=C2=A0 =C2=A0 =C2=A0 argp_help(state->root_argp,

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 stderr,

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ARGP_HELP_BUG_ADDR | ARGP_HELP_DOC | ARG=
P_HELP_USAGE | ARGP_HELP_LONG,

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 state->name);

=C2=A0 =C2=A0 =C2=A0 exit(1);



Compile and run without providing any arguments, I got a Segmentation fault=
.=C2=A0

The output looks like this:=C2=A0



Usage: t [-qsv?V] [-o FILE] [--output=3DFILE] [--quiet] [--silent] [--verbo=
se]

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [--help] [--usage] [--version] AR=
G1 ARG2

Argp example #3 -- a program with options and arguments using argp



=C2=A0 -o, --output=3DFILE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Output to FILE=
 instead of standard output

=C2=A0 -q, -s, --quiet, --silent=C2=A0 Don't produce any output

=C2=A0 -v, --verbose=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Produc=
e verbose output

=C2=A0 -?, --help =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 G=
ive this help list

=C2=A0 =C2=A0 =C2=A0 --usage=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Give a short usage message

=C2=A0 -V, Segmentation fault: 11



If I comment out these two lines:=C2=A0

21 =C2=A0 {"output", =C2=A0 'o', "FILE", 0,

22=C2=A0 =C2=A0 "Output to FILE instead of standard output" },



Things work perfectly.=C2=A0



On Redhat it is all ok.=C2=A0



I attached the modified example FYI.=C2=A0



Thanks for creating this wonderful piece.=C2=A0 :-0



Regards

Guangxin=C2=A0
------=_Part_36933_740982792.1628332162750
Content-Type: application/octet-stream; name=t.c
Content-Transfer-Encoding: 7bit
X-ZM_AttachId: 138476249627520040
Content-Disposition: attachment; filename=t.c

#include <stdlib.h>
#include <argp.h>

const char *argp_program_version =
  "argp-ex3 1.0";
const char *argp_program_bug_address =
  "<[email protected]>";

/* Program documentation. */
static char doc[] =
  "Argp example #3 -- a program with options and arguments using argp";

/* A description of the arguments we accept. */
static char args_doc[] = "ARG1 ARG2";

/* The options we understand. */
static struct argp_option options[] = {
  {"verbose",  'v', 0,      0,  "Produce verbose output" },
  {"quiet",    'q', 0,      0,  "Don't produce any output" },
  {"silent",   's', 0,      OPTION_ALIAS },
  {"output",   'o', "FILE", 0,
   "Output to FILE instead of standard output" },
  { 0 }
};

/* Used by main to communicate with parse_opt. */
struct arguments
{
  char *args[2];                /* arg1 & arg2 */
  int silent, verbose;
  char *output_file;
};

/* Parse a single option. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  /* Get the input argument from argp_parse, which we
     know is a pointer to our arguments structure. */
  struct arguments *arguments = state->input;

  switch (key)
    {
    case 'q': case 's':
      arguments->silent = 1;
      break;
    case 'v':
      arguments->verbose = 1;
      break;
    case 'o':
      arguments->output_file = arg;
      break;

    case ARGP_KEY_ARG:
      if (state->arg_num >= 2)
        /* Too many arguments. */
        argp_usage (state);

      arguments->args[state->arg_num] = arg;

      break;

    case ARGP_KEY_NO_ARGS:
      argp_help(state->root_argp,
          stderr,
          ARGP_HELP_BUG_ADDR | ARGP_HELP_DOC | ARGP_HELP_USAGE | ARGP_HELP_LONG,
          state->name);
      exit(1);

    case ARGP_KEY_END:
      if (state->arg_num < 2)
        /* Not enough arguments. */
        argp_usage (state);
      break;

    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}

/* Our argp parser. */
static struct argp argp = { options, parse_opt, args_doc, doc };

int
main (int argc, char **argv)
{
  struct arguments arguments;

  /* Default values. */
  arguments.silent = 0;
  arguments.verbose = 0;
  arguments.output_file = "-";

  /* Parse our arguments; every option seen by parse_opt will
     be reflected in arguments. */
  argp_parse (&argp, argc, argv, 0, 0, &arguments);

  printf ("ARG1 = %s\nARG2 = %s\nOUTPUT_FILE = %s\n"
          "VERBOSE = %s\nSILENT = %s\n",
          arguments.args[0], arguments.args[1],
          arguments.output_file,
          arguments.verbose ? "yes" : "no",
          arguments.silent ? "yes" : "no");

  exit (0);
}


------=_Part_36933_740982792.1628332162750--