From: Hannes Magnusson Date: Wed, 14 Nov 2007 15:19:29 +0000 (+0000) Subject: MFB5.3: Fixed bug#43293 (Multiple segfaults in getopt()) X-Git-Tag: php-5.2.6RC1~313 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d3fd30265ab692b23e05d52e55fb088a6b4eb515;p=php MFB5.3: Fixed bug#43293 (Multiple segfaults in getopt()) --- diff --git a/NEWS b/NEWS index bdd981866b..cfccaeef36 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2008, PHP 5.2.6 +- Fixed bug #43293 (Multiple segfaults in getopt()). (Hannes) - Fixed bug #43279 (pg_send_query_params() converts all elements in 'params' to strings). (Ilia) - Fixed bug #43248 (backward compatibility break in realpath()). (Dmitry) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index e58e8d51eb..da1129def9 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -4568,10 +4568,11 @@ PHP_FUNCTION(getopt) * in order to be on the safe side, even though it is also available * from the symbol table. */ - if (zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), (void **) &args) != FAILURE || - zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void **) &args) != FAILURE) { + if ((zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), (void **) &args) != FAILURE || + zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void **) &args) != FAILURE) && Z_TYPE_PP(args) == IS_ARRAY + ) { int pos = 0; - zval **arg; + zval **entry; argc = zend_hash_num_elements(Z_ARRVAL_PP(args)); @@ -4586,8 +4587,22 @@ PHP_FUNCTION(getopt) /* Iterate over the hash to construct the argv array. */ while (zend_hash_get_current_data(Z_ARRVAL_PP(args), - (void **)&arg) == SUCCESS) { - argv[pos++] = estrdup(Z_STRVAL_PP(arg)); + (void **)&entry) == SUCCESS) { + zval arg, *arg_ptr = *entry; + + if (Z_TYPE_PP(entry) != IS_STRING) { + arg = **entry; + zval_copy_ctor(&arg); + convert_to_string(&arg); + arg_ptr = &arg; + } + + argv[pos++] = estrdup(Z_STRVAL_P(arg_ptr)); + + if (arg_ptr != *entry) { + zval_dtor(&arg); + } + zend_hash_move_forward(Z_ARRVAL_PP(args)); } @@ -4605,7 +4620,7 @@ PHP_FUNCTION(getopt) #ifdef HARTMUT_0 int len, c = zend_hash_num_elements(Z_ARRVAL_P(p_longopts)); struct option *p; - zval **arg; + zval **entry; char *name; longopts = (struct option *)ecalloc(c+1, sizeof(struct option)); @@ -4618,10 +4633,19 @@ PHP_FUNCTION(getopt) /* Iterate over the hash to construct the argv array. */ while (zend_hash_get_current_data(Z_ARRVAL_P(p_longopts), - (void **)&arg) == SUCCESS) { + (void **)&entry) == SUCCESS) { + zval arg, *arg_ptr = *entry; + + if (Z_TYPE_PP(entry) != IS_STRING) { + arg = **entry; + zval_copy_ctor(&arg); + convert_to_string(&arg); + arg_ptr = &arg; + } + p->has_arg = 0; - name = estrdup(Z_STRVAL_PP(arg)); + name = estrdup(Z_STRVAL_P(arg_ptr)); len = strlen(name); if((len > 0) && (name[len-1] == ':')) { p->has_arg++; @@ -4636,6 +4660,10 @@ PHP_FUNCTION(getopt) p->flag = NULL; p->val = 0; + if (arg_ptr != *entry) { + zval_dtor(&arg); + } + zend_hash_move_forward(Z_ARRVAL_P(p_longopts)); p++; } diff --git a/ext/standard/tests/general_functions/bug43293_1.phpt b/ext/standard/tests/general_functions/bug43293_1.phpt new file mode 100644 index 0000000000..b4be252337 --- /dev/null +++ b/ext/standard/tests/general_functions/bug43293_1.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug#43293 (Multiple segfaults in getopt()) +--INI-- +register_argc_argv=Off +--FILE-- + +--EXPECT-- +array(0) { +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +bool(false) + diff --git a/ext/standard/tests/general_functions/bug43293_2.phpt b/ext/standard/tests/general_functions/bug43293_2.phpt new file mode 100644 index 0000000000..a91beebac6 --- /dev/null +++ b/ext/standard/tests/general_functions/bug43293_2.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug#43293 (Multiple segfaults in getopt()) +--INI-- +register_argc_argv=Off +--FILE-- + +--EXPECT-- +array(0) { +} + diff --git a/ext/standard/tests/general_functions/bug43293_3.phpt b/ext/standard/tests/general_functions/bug43293_3.phpt new file mode 100644 index 0000000000..6c846610bd --- /dev/null +++ b/ext/standard/tests/general_functions/bug43293_3.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug#43293 (Multiple segfaults in getopt()) +--SKIPIF-- + +--ARGS-- +-f --f +--INI-- +register_argc_argv=On +--FILE-- + +--EXPECT-- +array(1) { + ["f"]=> + array(2) { + [0]=> + bool(false) + [1]=> + bool(false) + } +} +array(3) { + [0]=> + bool(true) + [1]=> + bool(false) + [2]=> + string(1) "f" +} +