Skip to content

php_getopt() does not clear *optarg for long options with optional argument when value is absent — --ini regression in 8.5 #21901

Closed

Description

@mellonella

Description

In PHP 8.5 the --ini CLI option was changed from no_argument to optional_argument to support the new --ini=diff subcommand. As a side effect, --ini (without a value) now fails with Unknown argument for --ini whenever it is preceded on the command line by another option that takes a required argument.

Reproducer (PHP 8.5):

$ php --ini                       # OK
$ php -n --ini                    # OK   (-n takes no argument)
$ php -c /etc/php.ini --ini       # FAIL: Unknown argument for --ini
$ php -d foo=bar --ini            # FAIL: Unknown argument for --ini
$ php --ini -c /etc/php.ini       # OK   (workaround: reorder)

The same commands work correctly in PHP 8.4 and earlier.

Expected behavior:

--ini without a value should be treated identically regardless of its position on the command line, equivalent to --ini=.

Root cause:

In main/getopt.c, php_getopt() does not reset *optarg between calls. When a long option is declared with need_param == 2 (optional) and is supplied without =value, the function falls through without assigning *optarg, leaving it pointing at the value consumed by the previous option (e.g. the path passed to -c, or the assignment passed to -d). The CLI SAPI then interprets that stale value as the --ini subcommand, fails to match it against "" or "diff", and emits the error.

The bug existed before 8.5 but was never observable because no long option used optional_argument. The introduction of --ini=diff (and the corresponding flip of --ini to optional_argument) exposed it.

Affected versions: 8.5.0 and later (any build with --ini=diff support).


Proposed Patch

The simplest and most defensive fix is to clear *optarg at the top of php_getopt() so that callers never observe a stale pointer from a previous invocation, regardless of which code path is taken later.

--- main/getopt.c.orig	2026-03-10 19:15:23.000000000 -0400
+++ main/getopt.c	2026-04-24 06:11:15.038033405 -0400
@@ -59,6 +59,7 @@
 	static char **prev_optarg = NULL;
 
 	php_optidx = -1;
+	*optarg = NULL;
 
 	if(prev_optarg && prev_optarg != optarg) {
 		/* reset the state */

PHP Version

PHP 8.5.4 (cli) (built: Apr 24 2026 07:24:54) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.4, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.4, Copyright (c), by Zend Technologies

Operating System

Debian 12.13

Activity

  1. added a commit that references this issue on May 1, 2026
    893bc0a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions