mirror of
https://github.com/php/php-src.git
synced 2025-01-26 13:44:22 +08:00
Merge branch 'PHP-5.6' of git.php.net:php-src into PHP-5.6
This commit is contained in:
commit
0e18003374
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@
|
||||
*.tgz
|
||||
*.tar.gz
|
||||
*.tar.bz2
|
||||
*.tar.xz
|
||||
.FBCIndex
|
||||
.FBCLockFolder
|
||||
.deps
|
||||
|
@ -385,6 +385,12 @@ MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.0.4
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: hash
|
||||
PRIMARY MAINTAINER: Sara Golemon <pollita@php.net>, Mike Wallner <mike@php.net>, Anatol Belski <ab@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 5.1.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: iconv
|
||||
PRIMARY MAINTAINER: Moriyoshi Koizumi <moriyoshi@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
|
43
NEWS
43
NEWS
@ -1,7 +1,30 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 2014, PHP 5.6.2
|
||||
|
||||
?? ??? 2014, PHP 5.6.1
|
||||
- Core:
|
||||
. Fixed bug #67739 (Windows 8.1/Server 2012 R2 OS build number reported
|
||||
as 6.2 (instead of 6.3)). (Christian Wenz)
|
||||
. Fixed bug #67633 (A foreach on an array returned from a function not doing
|
||||
copy-on-write). (Nikita)
|
||||
. Fixed bug #51800 (proc_open on Windows hangs forever). (Anatol)
|
||||
. Fixed bug #68118 ($a->foo .= 'test'; can leave $a->foo undefined). (Nikita)
|
||||
|
||||
- FPM:
|
||||
. Fixed bug #65641 (PHP-FPM incorrectly defines the SCRIPT_NAME variable
|
||||
when using Apache, mod_proxy-fcgi and ProxyPass). (Remi)
|
||||
. Implemented FR #55508 (listen and listen.allowed_clients should take IPv6
|
||||
addresses). (Robin Gloster)
|
||||
|
||||
- Reflection:
|
||||
. Fixed bug #68103 (Duplicate entry in Reflection for class alias). (Remi)
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #68074 (Allow to use system cipher list instead of hardcoded
|
||||
value). (Remi)
|
||||
|
||||
|
||||
02 Oct 2014, PHP 5.6.1
|
||||
|
||||
- Core:
|
||||
. Implemented FR #38409 (parse_ini_file() looses the type of booleans). (Tjerk)
|
||||
@ -10,6 +33,13 @@ PHP NEWS
|
||||
. Fixed bug #67878 (program_prefix not honoured in man pages). (Remi)
|
||||
. Fixed bug #67938 (Segfault when extending interface method with variadic).
|
||||
(Nikita)
|
||||
. Fixed bug #67985 (Incorrect last used array index copied to new array after
|
||||
unset). (Tjerk)
|
||||
. Fixed bug #68088 (New Posthandler Potential Illegal efree() vulnerability).
|
||||
(Mike) (CVE-2014-3622)
|
||||
|
||||
- DOM:
|
||||
. Made DOMNode::textContent writeable. (Tjerk)
|
||||
|
||||
- Fileinfo:
|
||||
. Fixed bug #67731 (finfo::file() returns invalid mime type
|
||||
@ -29,11 +59,13 @@ PHP NEWS
|
||||
. Fixed bug #67839 (mysqli does not handle 4-byte floats correctly). (Keyur)
|
||||
|
||||
- OpenSSL:
|
||||
. Fixed bug #41631 (socket timeouts not honored in blocking SSL reads).
|
||||
(Daniel Lowrey)
|
||||
. Fixed bug #67850 (extension won't build if openssl compiled without SSLv3).
|
||||
(Daniel Lowrey)
|
||||
|
||||
- DOM:
|
||||
. Made DOMNode::textContent writeable. (Tjerk)
|
||||
- phpdbg:
|
||||
. Fixed issue krakjoe/phpdbg#111 (compile error without ZEND_SIGNALS). (Bob)
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug #67955 (SoapClient prepends 0-byte to cookie names). (Philip Hofstetter)
|
||||
@ -41,6 +73,10 @@ PHP NEWS
|
||||
- Session:
|
||||
. Fixed bug #67972 (SessionHandler Invalid memory read create_sid()). (Adam)
|
||||
|
||||
- Sysvsem:
|
||||
. Implemented FR #67990 (Add optional nowait argument to sem_acquire).
|
||||
(Matteo)
|
||||
|
||||
28 Aug 2014, PHP 5.6.0
|
||||
|
||||
- Apache2 Handler SAPI:
|
||||
@ -66,6 +102,7 @@ PHP NEWS
|
||||
. Fixed bug #66431 (Special Character via COM Interface (CP_UTF8)). (Anatol)
|
||||
|
||||
- Core:
|
||||
. Improved phpinfo() stylesheets. (Colin Viebrock)
|
||||
. Fixed bug #67693 (incorrect push to the empty array). (Tjerk)
|
||||
. Removed inconsistency regarding behaviour of array in constants at
|
||||
run-time. (Bob)
|
||||
|
44
Zend/tests/bug67633.phpt
Normal file
44
Zend/tests/bug67633.phpt
Normal file
@ -0,0 +1,44 @@
|
||||
--TEST--
|
||||
Bug #67633: A foreach on an array returned from a function not doing copy-on-write
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function id($x) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
function &ref_id(&$x) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
$c = 'c';
|
||||
$array = ['a', 'b', $c];
|
||||
|
||||
foreach(id($array) as &$v) {
|
||||
$v .= 'q';
|
||||
}
|
||||
var_dump($array);
|
||||
|
||||
foreach(ref_id($array) as &$v) {
|
||||
$v .= 'q';
|
||||
}
|
||||
var_dump($array);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
[2]=>
|
||||
string(1) "c"
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(2) "aq"
|
||||
[1]=>
|
||||
string(2) "bq"
|
||||
[2]=>
|
||||
&string(2) "cq"
|
||||
}
|
16
Zend/tests/bug67985.phpt
Normal file
16
Zend/tests/bug67985.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #67985 - Last used array index not copied to new array at assignment
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$a = ['zero', 'one', 'two'];
|
||||
unset($a[2]);
|
||||
$b = $a;
|
||||
$a[] = 'three';
|
||||
$b[] = 'three';
|
||||
|
||||
var_dump($a === $b);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
21
Zend/tests/bug68118.phpt
Normal file
21
Zend/tests/bug68118.phpt
Normal file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Bug #68118: $a->foo .= 'test'; can leave $a->foo undefined
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
set_error_handler(function() {
|
||||
$obj = new stdClass;
|
||||
$obj->test = 'meow';
|
||||
return true;
|
||||
});
|
||||
|
||||
$a = new stdClass;
|
||||
$a->undefined .= 'test';
|
||||
var_dump($a);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
object(stdClass)#2 (1) {
|
||||
["undefined"]=>
|
||||
string(4) "test"
|
||||
}
|
@ -6337,6 +6337,15 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
|
||||
/* save the location of FETCH_W instruction(s) */
|
||||
open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
|
||||
zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
|
||||
|
||||
if (zend_is_function_or_method_call(array)) {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_SEPARATE;
|
||||
SET_NODE(opline->op1, array);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->result_type = IS_VAR;
|
||||
opline->result.var = opline->op1.var;
|
||||
}
|
||||
} else {
|
||||
is_variable = 0;
|
||||
open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
|
||||
|
@ -786,9 +786,6 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, int type
|
||||
/* we don't have access controls - will just add it */
|
||||
new_zval = &EG(uninitialized_zval);
|
||||
|
||||
if(UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
|
||||
zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
|
||||
}
|
||||
Z_ADDREF_P(new_zval);
|
||||
if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
|
||||
property_info->offset >= 0) {
|
||||
@ -808,6 +805,12 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, int type
|
||||
}
|
||||
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
|
||||
}
|
||||
|
||||
/* Notice is thrown after creation of the property, to avoid EG(std_property_info)
|
||||
* being overwritten in an error handler. */
|
||||
if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
|
||||
zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
|
||||
}
|
||||
} else {
|
||||
/* we do have getter - fail and let it try again with usual get/set */
|
||||
retval = NULL;
|
||||
|
@ -138,6 +138,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
ALLOC_HASHTABLE_REL(tmp_ht);
|
||||
zend_hash_init(tmp_ht, zend_hash_num_elements(original_ht), NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_copy(tmp_ht, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
||||
tmp_ht->nNextFreeElement = original_ht->nNextFreeElement;
|
||||
zvalue->value.ht = tmp_ht;
|
||||
}
|
||||
break;
|
||||
|
32
configure.in
32
configure.in
@ -119,7 +119,7 @@ int zend_sprintf(char *buffer, const char *format, ...);
|
||||
|
||||
PHP_MAJOR_VERSION=5
|
||||
PHP_MINOR_VERSION=6
|
||||
PHP_RELEASE_VERSION=1
|
||||
PHP_RELEASE_VERSION=2
|
||||
PHP_EXTRA_VERSION="-dev"
|
||||
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
|
||||
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
|
||||
@ -787,7 +787,12 @@ if test "$PHP_GCOV" = "yes"; then
|
||||
AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
|
||||
fi
|
||||
|
||||
ltp_version_list="1.5 1.6 1.7 1.9 1.10"
|
||||
dnl min: 1.5 (i.e. 105, major * 100 + minor for easier comparison)
|
||||
ltp_version_min="105"
|
||||
dnl non-working versions, e.g. "1.8 1.18";
|
||||
dnl remove "none" when introducing the first incompatible LTP version an
|
||||
dnl separate any following additions by spaces
|
||||
ltp_version_exclude="1.8"
|
||||
|
||||
AC_CHECK_PROG(LTP, lcov, lcov)
|
||||
AC_CHECK_PROG(LTP_GENHTML, genhtml, genhtml)
|
||||
@ -797,21 +802,30 @@ if test "$PHP_GCOV" = "yes"; then
|
||||
if test "$LTP"; then
|
||||
AC_CACHE_CHECK([for ltp version], php_cv_ltp_version, [
|
||||
php_cv_ltp_version=invalid
|
||||
ltp_version=`$LTP -v 2>/dev/null | $SED -e 's/^.* //'`
|
||||
for ltp_check_version in $ltp_version_list; do
|
||||
if test "$ltp_version" = "$ltp_check_version"; then
|
||||
php_cv_ltp_version="$ltp_check_version (ok)"
|
||||
ltp_version_vars=`$LTP -v 2>/dev/null | $SED -e 's/^.* //' -e 's/\./ /g' | tr -d a-z`
|
||||
if test -n "$ltp_version_vars"; then
|
||||
set $ltp_version_vars
|
||||
ltp_version="${1}.${2}"
|
||||
ltp_version_num="`expr ${1} \* 100 + ${2}`"
|
||||
if test $ltp_version_num -ge $ltp_version_min; then
|
||||
php_cv_ltp_version="$ltp_version (ok)"
|
||||
for ltp_check_version in $ltp_version_exclude; do
|
||||
if test "$ltp_version" = "$ltp_check_version"; then
|
||||
php_cv_ltp_version=invalid
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
else
|
||||
ltp_msg="To enable code coverage reporting you must have one of the following LTP versions installed: $ltp_version_list"
|
||||
ltp_msg="To enable code coverage reporting you must have LTP installed"
|
||||
AC_MSG_ERROR([$ltp_msg])
|
||||
fi
|
||||
|
||||
case $php_cv_ltp_version in
|
||||
""|invalid[)]
|
||||
ltp_msg="You must have one of the following versions of LTP: $ltp_version_list (found: $ltp_version)."
|
||||
ltp_msg="This LTP version is not supported (found: $ltp_version, min: $ltp_version_min, excluded: $ltp_version_exclude)."
|
||||
AC_MSG_ERROR([$ltp_msg])
|
||||
LTP="exit 0;"
|
||||
;;
|
||||
|
@ -28,7 +28,7 @@ Features
|
||||
AsynchDNS => Yes
|
||||
CharConv => No
|
||||
Debug => No
|
||||
GSS-Negotiate => Yes
|
||||
GSS-Negotiate => No
|
||||
IDN => Yes
|
||||
IPv6 => Yes
|
||||
krb4 => No
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -156,12 +156,12 @@ if test "\$PHP_$EXTNAME" != "no"; then
|
||||
|
||||
dnl PHP_CHECK_LIBRARY(\$LIBNAME,\$LIBSYMBOL,
|
||||
dnl [
|
||||
dnl PHP_ADD_LIBRARY_WITH_PATH(\$LIBNAME, \$${EXTNAME}_DIR/lib, ${EXTNAME}_SHARED_LIBADD)
|
||||
dnl PHP_ADD_LIBRARY_WITH_PATH(\$LIBNAME, \$${EXTNAME}_DIR/\$PHP_LIBDIR, ${EXTNAME}_SHARED_LIBADD)
|
||||
dnl AC_DEFINE(HAVE_${EXTNAME}LIB,1,[ ])
|
||||
dnl ],[
|
||||
dnl AC_MSG_ERROR([wrong $extname lib version or lib not found])
|
||||
dnl ],[
|
||||
dnl -L\$${EXTNAME}_DIR/lib -lm
|
||||
dnl -L\$${EXTNAME}_DIR/\$PHP_LIBDIR -lm
|
||||
dnl ])
|
||||
dnl
|
||||
dnl PHP_SUBST(${EXTNAME}_SHARED_LIBADD)
|
||||
|
@ -1272,7 +1272,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
|
||||
* the sign extension must have happened.
|
||||
*/
|
||||
case FILE_BYTE:
|
||||
v = (char) v;
|
||||
v = (signed char) v;
|
||||
break;
|
||||
case FILE_SHORT:
|
||||
case FILE_BESHORT:
|
||||
|
@ -1,13 +1,12 @@
|
||||
--TEST--
|
||||
Bug #48801 (Problem with imagettfbbox) freetype >= 2.4.10 and < 2.4.12
|
||||
Bug #48801 (Problem with imagettfbbox) freetype >= 2.4.10
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded('gd')){ die('skip gd extension not available'); }
|
||||
if(!function_exists('imageftbbox')) die('skip imageftbbox() not available');
|
||||
|
||||
include dirname(__FILE__) . '/func.inc';
|
||||
if(version_compare(get_freetype_version(), '2.4.10') < 0) die('skip for freetype >= 2.4.10');
|
||||
if(version_compare(get_freetype_version(), '2.4.12') >= 0) die('skip for freetype < 2.4.12');
|
||||
if(version_compare(get_freetype_version(), '2.4.10') == -1) die('skip for freetype >= 2.4.10');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
@ -21,6 +20,6 @@ echo '(' . $bbox[6] . ', ' . $bbox[7] . ")\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
(-1, 15)
|
||||
(156, 15)
|
||||
(156, -48)
|
||||
(15%d, 15)
|
||||
(15%d, -48)
|
||||
(-1, -48)
|
||||
|
@ -1,25 +0,0 @@
|
||||
--TEST--
|
||||
Bug #48801 (Problem with imagettfbbox) freetype >= 2.4.12
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded('gd')){ die('skip gd extension not available'); }
|
||||
if(!function_exists('imageftbbox')) die('skip imageftbbox() not available');
|
||||
|
||||
include dirname(__FILE__) . '/func.inc';
|
||||
if(version_compare(get_freetype_version(), '2.4.12') < 0) die('skip for freetype >= 2.4.12');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$cwd = dirname(__FILE__);
|
||||
$font = "$cwd/Tuffy.ttf";
|
||||
$bbox = imageftbbox(50, 0, $font, "image");
|
||||
echo '(' . $bbox[0] . ', ' . $bbox[1] . ")\n";
|
||||
echo '(' . $bbox[2] . ', ' . $bbox[3] . ")\n";
|
||||
echo '(' . $bbox[4] . ', ' . $bbox[5] . ")\n";
|
||||
echo '(' . $bbox[6] . ', ' . $bbox[7] . ")\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
(-1, 15)
|
||||
(155, 15)
|
||||
(155, -48)
|
||||
(-1, -48)
|
@ -391,6 +391,23 @@ static int _get_lderrno(LDAP *ldap)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _set_lderrno
|
||||
*/
|
||||
static void _set_lderrno(LDAP *ldap, int lderr)
|
||||
{
|
||||
#if !HAVE_NSLDAP
|
||||
#if LDAP_API_VERSION > 2000 || HAVE_ORALDAP
|
||||
/* New versions of OpenLDAP do it this way */
|
||||
ldap_set_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
|
||||
#else
|
||||
ldap->ld_errno = lderr;
|
||||
#endif
|
||||
#else
|
||||
ldap_set_lderrno(ldap, lderr, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool ldap_bind(resource link [, string dn [, string password]])
|
||||
Bind to LDAP directory */
|
||||
PHP_FUNCTION(ldap_bind)
|
||||
@ -405,18 +422,20 @@ PHP_FUNCTION(ldap_bind)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
|
||||
|
||||
if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
|
||||
_set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "DN contains a null byte");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
|
||||
_set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password contains a null byte");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
|
||||
|
||||
if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
|
||||
RETURN_FALSE;
|
||||
|
@ -200,17 +200,27 @@ ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
|
||||
/* The following cast is guaranteed to do the right thing */
|
||||
dval = (double) d32val;
|
||||
}
|
||||
#elif defined(PHP_WIN32)
|
||||
{
|
||||
/* float datatype on Winows is already 4 byte but has a precision of 7 digits */
|
||||
char num_buf[2048];
|
||||
(void)_gcvt_s(num_buf, 2048, fval, field->decimals >= 31 ? 7 : field->decimals);
|
||||
dval = zend_strtod(num_buf, NULL);
|
||||
}
|
||||
#else
|
||||
{
|
||||
char num_buf[2048]; /* Over allocated */
|
||||
char *s;
|
||||
|
||||
#ifndef FLT_DIG
|
||||
# define FLT_DIG 6
|
||||
#endif
|
||||
/* Convert to string. Ignoring localization, etc.
|
||||
* Following MySQL's rules. If precision is undefined (NOT_FIXED_DEC i.e. 31)
|
||||
* or larger than 31, the value is limited to 6 (FLT_DIG).
|
||||
*/
|
||||
s = php_gcvt(fval,
|
||||
field->decimals >= 31 ? 6 : field->decimals,
|
||||
field->decimals >= 31 ? FLT_DIG : field->decimals,
|
||||
'.',
|
||||
'e',
|
||||
num_buf);
|
||||
|
@ -8,6 +8,9 @@ PHP_ARG_WITH(openssl, for OpenSSL support,
|
||||
PHP_ARG_WITH(kerberos, for Kerberos support,
|
||||
[ --with-kerberos[=DIR] OPENSSL: Include Kerberos support], no, no)
|
||||
|
||||
PHP_ARG_WITH(system-ciphers, whether to use system default cipher list instead of hardcoded value,
|
||||
[ --with-system-ciphers OPENSSL: Use system default cipher list instead of hardcoded value], no, no)
|
||||
|
||||
if test "$PHP_OPENSSL" != "no"; then
|
||||
PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_shared)
|
||||
PHP_SUBST(OPENSSL_SHARED_LIBADD)
|
||||
@ -25,4 +28,7 @@ if test "$PHP_OPENSSL" != "no"; then
|
||||
], [
|
||||
AC_MSG_ERROR([OpenSSL check failed. Please check config.log for more information.])
|
||||
])
|
||||
if test "$PHP_SYSTEM_CIPHERS" != "no"; then
|
||||
AC_DEFINE(USE_OPENSSL_SYSTEM_CIPHERS,1,[ Use system default cipher list instead of hardcoded value ])
|
||||
fi
|
||||
fi
|
||||
|
@ -1,28 +1,28 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICCTCCAXICCQDNMI29sowT7TANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJT
|
||||
MIICCTCCAXICCQCx2JwIhbRefzANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJT
|
||||
RzESMBAGA1UECBMJVGVzdHZpbGxlMREwDwYDVQQKEwhkYXRpYmJhdzETMBEGA1UE
|
||||
AxQKKi50ZXN0LmNvbTAeFw0xMzA5MjEwNzUyMjRaFw0xNDA5MjEwNzUyMjRaMEkx
|
||||
AxQKKi50ZXN0LmNvbTAeFw0xNDA5MjQxMTMzNTRaFw0yNDA5MjExMTMzNTRaMEkx
|
||||
CzAJBgNVBAYTAlNHMRIwEAYDVQQIEwlUZXN0dmlsbGUxETAPBgNVBAoTCGRhdGli
|
||||
YmF3MRMwEQYDVQQDFAoqLnRlc3QuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||
iQKBgQCdzVnic8K5W4SVbwVuqezcTjeqVLoQ91vVNZB0Jnsuz6q3DoK03oAd1jTe
|
||||
Vd0k+MQDbXpHoc37lA4+8z/g5Bs0UXxNx+nkbFTE7Ba2/G24caI9/cOXZPG3UViD
|
||||
rtqXKL6h5/umqRG9Dt5liF2MVP9XFAesVC7B8+Ca+PbPlQoYzwIDAQABMA0GCSqG
|
||||
SIb3DQEBBQUAA4GBAAS07u/Ke+EhEHidz6CG3Qcr+zg483JKRgZFyGz+YUKyyKKy
|
||||
fmLs7JieGJxYQjOmIpj/6X9Gnb2HjIPDnI6A+MV1emXDTnnmsgf2/lZGcthhpZn2
|
||||
rMbj9bI0iH6HwOVGtp4ZJA5fB7nj3J+gWNTCQzDDOxwX36d2LL9ua+UMnk/g
|
||||
iQKBgQDBnR8DYzsN90kISI87kBvw40TQknS7/fuymWCmSrtRQLED8p2QL8PiYCZ8
|
||||
UdcFVsv+di7MJvUOzW6dRo2DCu8Rojx3ML8dAtPsQkDdaCXDnOvCTQCAqFmxa1A9
|
||||
c5kp0hbzCrucKGckb355A4NumFgX1fjQ705MfjGPgQef1ZtozQIDAQABMA0GCSqG
|
||||
SIb3DQEBBQUAA4GBAGP07nJo0pI4FdsXuAHWr97XxV4EhHopFMw6svOZ3UtsRzmW
|
||||
ScmmMdgd3c8ciVxOsztgnzvFq/nrUkw/3n/Xz/gtE7kZt9aS18SnCyyHPJcXmmUE
|
||||
NsbyZ/7srIqCSrxUkP+N//nToqHxg1pqA/A8RzOOQUAp+UIVF6Zl/kkFNgt8
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQCdzVnic8K5W4SVbwVuqezcTjeqVLoQ91vVNZB0Jnsuz6q3DoK0
|
||||
3oAd1jTeVd0k+MQDbXpHoc37lA4+8z/g5Bs0UXxNx+nkbFTE7Ba2/G24caI9/cOX
|
||||
ZPG3UViDrtqXKL6h5/umqRG9Dt5liF2MVP9XFAesVC7B8+Ca+PbPlQoYzwIDAQAB
|
||||
AoGAeyzTwKPDl5QMRejHQL57GOwlH1vLcXrjv+VzwHZZKQ0IoKM++5fCQYf29KXp
|
||||
XPahaluGW2u9sWa8R/7wGcd0Q4RtquGzsgT3+AQsIc5KfIamyOyDaRVM/ymX3fWg
|
||||
gHIU7OOzB+ihOU8sHyRIwfbk01/kmrBXLRj8E31sy3i3PIECQQDQQYE+aN7Acrdt
|
||||
yN5CaqvbkiCGjRvASlemiTzPosgOtndyp21w1gakJwKYhYDk1N6A6Qb8REMZqM/U
|
||||
wFypldV/AkEAwfq6NFuhpGL6hDA7MvlyY1KiZ0cHetPUX+PgdNqy2DA+1Sv4i7gm
|
||||
Wd/uA651K7aPXuUaf9dKtPCmZwI4M6SEsQJBALW89HTqP7niYoDEEnITdPaghxHk
|
||||
gptERUln6lGo1L1CLus3gSI/JHyMLo+7scgAnEwTD62GRKhX0Ubwt+ymfTECQAY5
|
||||
fHYnppU20+EgBxZIqOIFCc8UmWnYmE0Ha/Fz/x8u1SVUBuK84wYpSGL32yyu7ATY
|
||||
hzQo/W229zABAzqtAdECQQCUdB7IBFpPnsfv/EUBFX7X/7zAc9JpACmu9It5ju8C
|
||||
KIsMuz/02D+TQoJNjdAngBM+4AJDIaGFgTMIfaDMh5L7
|
||||
MIICXgIBAAKBgQDBnR8DYzsN90kISI87kBvw40TQknS7/fuymWCmSrtRQLED8p2Q
|
||||
L8PiYCZ8UdcFVsv+di7MJvUOzW6dRo2DCu8Rojx3ML8dAtPsQkDdaCXDnOvCTQCA
|
||||
qFmxa1A9c5kp0hbzCrucKGckb355A4NumFgX1fjQ705MfjGPgQef1ZtozQIDAQAB
|
||||
AoGADAnkAsbpxh2JKf2xAkgcpKbNAZcJsSLCwsEstEpTSWMXXqJ4T53YtTu7SOGh
|
||||
2BAkkQbyM/l8JVZ6uUbIx8wnPzqAuB2hEDQHKZVyftDyJh+54Uyz0xV0JdWGWrFh
|
||||
A+uDt/Zncx2g+qlkQG5J5nHnrd9OAns89wJXpBWA6twlsuECQQD/HC4wxOJzh1XI
|
||||
YSWHWQulOnlNgZ2zERfmJeRfJ0ncmDOV2ofxOFQ+dMJ36XghPaH52KdxqWI1yQaE
|
||||
yesx8ygFAkEAwkoF4lBuYdsXucJNDYf8o9MlBvazoriH0y26B/YozJ7iAEFqVvcC
|
||||
TN+iKDIyiRALwR6a3nzhyFYJ4xyzgSIAKQJBAMnw3seQMsnM6aTS8cgwPr2uifNG
|
||||
lTT4ZPi0KhEAosFSYhNPh6j1NAq0lnQhhgyaIywJypJ4yNtWpChdRiamGpkCQQDB
|
||||
iUExPpOmMLwCk7VzrCmS+6pftHIevpi2WU99zMy5f+969665MFb/QqniRpamh/Bd
|
||||
kGIPDPFQQbyZmqaJFNh5AkEAzy0YVbUT3C/QvstPr5i7ztj7WiW/1zJMamFwY/ZS
|
||||
1J7e7lqHgRICie5uv1Yvh3w/qmV/7lTLhmlQZd9SJMpXhg==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
@ -1476,13 +1476,16 @@ int php_openssl_setup_crypto(php_stream *stream,
|
||||
}
|
||||
|
||||
GET_VER_OPT_STRING("ciphers", cipherlist);
|
||||
#ifndef USE_OPENSSL_SYSTEM_CIPHERS
|
||||
if (!cipherlist) {
|
||||
cipherlist = OPENSSL_DEFAULT_STREAM_CIPHERS;
|
||||
}
|
||||
if (SSL_CTX_set_cipher_list(sslsock->ctx, cipherlist) != 1) {
|
||||
return FAILURE;
|
||||
#endif
|
||||
if (cipherlist) {
|
||||
if (SSL_CTX_set_cipher_list(sslsock->ctx, cipherlist) != 1) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILURE == set_local_cert(sslsock->ctx, stream TSRMLS_CC)) {
|
||||
return FAILURE;
|
||||
}
|
||||
@ -1849,7 +1852,7 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun
|
||||
to hang forever. To avoid this scenario we poll with a timeout before performing
|
||||
the actual read. If it times out we're finished.
|
||||
*/
|
||||
if (sock->is_blocked) {
|
||||
if (sock->is_blocked && SSL_pending(sslsock->ssl_handle) == 0) {
|
||||
php_openssl_stream_wait_for_data(sock);
|
||||
if (sock->timeout_event) {
|
||||
stream->eof = 1;
|
||||
@ -2176,17 +2179,19 @@ static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TS
|
||||
|
||||
case PHP_STREAM_AS_FD_FOR_SELECT:
|
||||
if (ret) {
|
||||
if (sslsock->ssl_active) {
|
||||
/* OpenSSL has an internal buffer which select() cannot see. If we don't
|
||||
fetch it into the stream's buffer, no activity will be reported on the
|
||||
stream even though there is data waiting to be read - but we only fetch
|
||||
the number of bytes OpenSSL has ready to give us since we weren't asked
|
||||
for any data at this stage. This is only likely to cause issues with
|
||||
non-blocking streams, but it's harmless to always do it. */
|
||||
int bytes;
|
||||
while ((bytes = SSL_pending(sslsock->ssl_handle)) > 0) {
|
||||
php_stream_fill_read_buffer(stream, (size_t)bytes);
|
||||
}
|
||||
/* OpenSSL has an internal buffer which select() cannot see. If we don't
|
||||
* fetch it into the stream's buffer, no activity will be reported on the
|
||||
* stream even though there is data waiting to be read - but we only fetch
|
||||
* the lower of bytes OpenSSL has ready to give us or chunk_size since we
|
||||
* weren't asked for any data at this stage. This is only likely to cause
|
||||
* issues with non-blocking streams, but it's harmless to always do it. */
|
||||
size_t pending;
|
||||
if (stream->writepos == stream->readpos
|
||||
&& sslsock->ssl_active
|
||||
&& (pending = (size_t)SSL_pending(sslsock->ssl_handle)) > 0) {
|
||||
php_stream_fill_read_buffer(stream, pending < stream->chunk_size
|
||||
? pending
|
||||
: stream->chunk_size);
|
||||
}
|
||||
|
||||
*(php_socket_t *)ret = sslsock->s.socket;
|
||||
|
@ -1015,9 +1015,12 @@ static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_arg
|
||||
int *num_classes = va_arg(args, int*);
|
||||
|
||||
if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
|
||||
string_printf(str, "\n");
|
||||
_class_string(str, *pce, NULL, indent TSRMLS_CC);
|
||||
(*num_classes)++;
|
||||
/* dump class if it is not an alias */
|
||||
if (!zend_binary_strcasecmp((*pce)->name, (*pce)->name_length, hash_key->arKey, hash_key->nKeyLength-1)) {
|
||||
string_printf(str, "\n");
|
||||
_class_string(str, *pce, NULL, indent TSRMLS_CC);
|
||||
(*num_classes)++;
|
||||
}
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
@ -5395,12 +5398,24 @@ static int add_extension_class(zend_class_entry **pce TSRMLS_DC, int num_args, v
|
||||
int add_reflection_class = va_arg(args, int);
|
||||
|
||||
if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
|
||||
const char *name;
|
||||
int nlen;
|
||||
|
||||
if (zend_binary_strcasecmp((*pce)->name, (*pce)->name_length, hash_key->arKey, hash_key->nKeyLength-1)) {
|
||||
/* This is an class alias, use alias name */
|
||||
name = hash_key->arKey;
|
||||
nlen = hash_key->nKeyLength-1;
|
||||
} else {
|
||||
/* Use class name */
|
||||
name = (*pce)->name;
|
||||
nlen = (*pce)->name_length;
|
||||
}
|
||||
if (add_reflection_class) {
|
||||
ALLOC_ZVAL(zclass);
|
||||
zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
|
||||
add_assoc_zval_ex(class_array, (*pce)->name, (*pce)->name_length + 1, zclass);
|
||||
add_assoc_zval_ex(class_array, name, nlen+1, zclass);
|
||||
} else {
|
||||
add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length, 1);
|
||||
add_next_index_stringl(class_array, name, nlen, 1);
|
||||
}
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
|
@ -365,8 +365,8 @@ static unsigned short php_read2(php_stream * stream TSRMLS_DC)
|
||||
{
|
||||
unsigned char a[2];
|
||||
|
||||
/* just return 0 if we hit the end-of-file */
|
||||
if((php_stream_read(stream, a, sizeof(a))) <= 0) return 0;
|
||||
/* return 0 if we couldn't read enough data */
|
||||
if((php_stream_read(stream, a, sizeof(a))) < sizeof(a)) return 0;
|
||||
|
||||
return (((unsigned short)a[0]) << 8) + ((unsigned short)a[1]);
|
||||
}
|
||||
@ -646,7 +646,7 @@ static struct gfxinfo *php_handle_jpc(php_stream * stream TSRMLS_DC)
|
||||
#endif
|
||||
|
||||
result->channels = php_read2(stream TSRMLS_CC); /* Csiz */
|
||||
if (result->channels < 0 || result->channels > 256) {
|
||||
if (result->channels == 0 && php_stream_eof(stream) || result->channels > 256) {
|
||||
efree(result);
|
||||
return NULL;
|
||||
}
|
||||
|
95
ext/standard/tests/streams/proc_open_bug51800.phpt
Normal file
95
ext/standard/tests/streams/proc_open_bug51800.phpt
Normal file
@ -0,0 +1,95 @@
|
||||
--TEST--
|
||||
Bug #51800 proc_open on Windows hangs forever
|
||||
--SKIPIF--
|
||||
<?php
|
||||
echo 'skip expected to fail or take too long';
|
||||
if (getenv("SKIP_SLOW_TESTS")) {
|
||||
die("skip slow test");
|
||||
}
|
||||
?>
|
||||
--XFAIL--
|
||||
pipes have to be read/written simultaneously
|
||||
--FILE--
|
||||
<?php
|
||||
/* This is the wrong way to do it. The parent will block till it has read all the STDIN.
|
||||
The smaller the pipe buffer is, the longer it will take. It might even pass at the end,
|
||||
after taking inappropriately long. Pipes have to be read simultaneously in smaller chunks,
|
||||
so then the pipe buffer is emptied more often and the child has chance to continue its
|
||||
write. The behaviour might look some better if write/read in a separate thread, however
|
||||
this is much more resource greedy and complexer to integrate into the user script. */
|
||||
|
||||
$callee = dirname(__FILE__) . "/process_proc_open_bug51800.php";
|
||||
$php = PHP_BINARY;
|
||||
$cmd = "$php $callee";
|
||||
|
||||
$status;
|
||||
$stdout = "";
|
||||
$stderr = "";
|
||||
$pipes = array();
|
||||
|
||||
$descriptors = array(
|
||||
0 => array("pipe", "rb"), // stdin
|
||||
1 => array("pipe", "wb"), // stdout
|
||||
2 => array("pipe", "wb") // stderr
|
||||
);
|
||||
|
||||
/* create the proc file */
|
||||
$r = file_put_contents($callee, '<?php
|
||||
|
||||
$how_much = 10000;
|
||||
|
||||
$data0 = str_repeat("a", $how_much);
|
||||
$data1 = str_repeat("b", $how_much);
|
||||
fwrite(STDOUT, $data0);
|
||||
fwrite(STDERR, $data1);
|
||||
|
||||
exit(0);
|
||||
');
|
||||
|
||||
if (!$r) {
|
||||
die("couldn't create helper script '$callee'");
|
||||
}
|
||||
|
||||
$process = proc_open($cmd, $descriptors, $pipes);
|
||||
|
||||
if (is_resource($process))
|
||||
{
|
||||
fclose($pipes[0]);
|
||||
|
||||
while (!feof($pipes[1]))
|
||||
$stdout .= fread($pipes[1], 1024);
|
||||
fclose($pipes[1]);
|
||||
|
||||
while (!feof($pipes[2]))
|
||||
$stderr .= fread($pipes[2], 1024);
|
||||
fclose($pipes[2]);
|
||||
|
||||
$status = proc_close($process);
|
||||
}
|
||||
|
||||
var_dump(array(
|
||||
"status" => $status,
|
||||
"stdout" => $stdout,
|
||||
"stderr" => $stderr,
|
||||
), strlen($stdout), strlen($stderr));
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--CLEAN--
|
||||
<?php
|
||||
$callee = dirname(__FILE__) . "/process_proc_open_bug51800.php";
|
||||
unlink($callee);
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
["status"]=>
|
||||
int(0)
|
||||
["stdout"]=>
|
||||
string(10000) "a%s"
|
||||
["stderr"]=>
|
||||
string(10000) "b%s"
|
||||
}
|
||||
int(10000)
|
||||
int(10000)
|
||||
===DONE===
|
||||
|
78
ext/standard/tests/streams/proc_open_bug51800_right.phpt
Normal file
78
ext/standard/tests/streams/proc_open_bug51800_right.phpt
Normal file
@ -0,0 +1,78 @@
|
||||
--TEST--
|
||||
Bug #51800 proc_open on Windows hangs forever, the right way to do it
|
||||
--FILE--
|
||||
<?php
|
||||
$callee = dirname(__FILE__) . "/process_proc_open_bug51800_right.php";
|
||||
$php = PHP_BINARY;
|
||||
$cmd = "$php $callee";
|
||||
|
||||
$status;
|
||||
$stdout = "";
|
||||
$stderr = "";
|
||||
$pipes = array();
|
||||
|
||||
$descriptors = array(
|
||||
0 => array("pipe", "rb"), // stdin
|
||||
1 => array("pipe", "wb"), // stdout
|
||||
2 => array("pipe", "wb") // stderr
|
||||
);
|
||||
|
||||
/* create the proc file */
|
||||
$r = file_put_contents($callee, '<?php
|
||||
|
||||
$how_much = 10000;
|
||||
|
||||
$data0 = str_repeat("a", $how_much);
|
||||
$data1 = str_repeat("b", $how_much);
|
||||
fwrite(STDOUT, $data0);
|
||||
fwrite(STDERR, $data1);
|
||||
|
||||
exit(0);
|
||||
');
|
||||
|
||||
if (!$r) {
|
||||
die("couldn't create helper script '$callee'");
|
||||
}
|
||||
|
||||
$process = proc_open($cmd, $descriptors, $pipes);
|
||||
|
||||
if (is_resource($process))
|
||||
{
|
||||
fclose($pipes[0]);
|
||||
|
||||
while (!feof($pipes[1]) || !feof($pipes[2])) {
|
||||
$stdout .= fread($pipes[1], 1024);
|
||||
$stderr .= fread($pipes[2], 1024);
|
||||
}
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
$status = proc_close($process);
|
||||
}
|
||||
|
||||
var_dump(array(
|
||||
"status" => $status,
|
||||
"stdout" => $stdout,
|
||||
"stderr" => $stderr,
|
||||
), strlen($stdout), strlen($stderr));
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--CLEAN--
|
||||
<?php
|
||||
$callee = dirname(__FILE__) . "/process_proc_open_bug51800_right.php";
|
||||
unlink($callee);
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
["status"]=>
|
||||
int(0)
|
||||
["stdout"]=>
|
||||
string(10000) "a%s"
|
||||
["stderr"]=>
|
||||
string(10000) "b%s"
|
||||
}
|
||||
int(10000)
|
||||
int(10000)
|
||||
===DONE===
|
||||
|
84
ext/standard/tests/streams/proc_open_bug51800_right2.phpt
Normal file
84
ext/standard/tests/streams/proc_open_bug51800_right2.phpt
Normal file
@ -0,0 +1,84 @@
|
||||
--TEST--
|
||||
Bug #51800 proc_open on Windows hangs forever, the right way to do it with more data
|
||||
--FILE--
|
||||
<?php
|
||||
$callee = dirname(__FILE__) . "/process_proc_open_bug51800_right2.php";
|
||||
$php = PHP_BINARY;
|
||||
$cmd = "$php $callee";
|
||||
|
||||
$status;
|
||||
$stdout = "";
|
||||
$stderr = "";
|
||||
$pipes = array();
|
||||
|
||||
$descriptors = array(
|
||||
0 => array("pipe", "rb"), // stdin
|
||||
1 => array("pipe", "wb"), // stdout
|
||||
2 => array("pipe", "wb") // stderr
|
||||
);
|
||||
|
||||
/* create the proc file */
|
||||
$r = file_put_contents($callee, '<?php
|
||||
$how_much = 1000000;
|
||||
|
||||
$data0 = str_repeat("a", $how_much);
|
||||
$data1 = str_repeat("b", $how_much);
|
||||
$i0 = $i1 = 0;
|
||||
$step = 1024;
|
||||
|
||||
while ($i0 < strlen($data0) && $i1 < strlen($data1)) {
|
||||
fwrite(STDOUT, substr($data0, $i0, $step));
|
||||
fwrite(STDERR, substr($data1, $i1, $step));
|
||||
$i0 += $step;
|
||||
$i1 += $step;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
');
|
||||
|
||||
if (!$r) {
|
||||
die("couldn't create helper script '$callee'");
|
||||
}
|
||||
|
||||
$process = proc_open($cmd, $descriptors, $pipes);
|
||||
|
||||
if (is_resource($process))
|
||||
{
|
||||
fclose($pipes[0]);
|
||||
|
||||
while (!feof($pipes[1]) || !feof($pipes[2])) {
|
||||
$stdout .= fread($pipes[1], 1024);
|
||||
$stderr .= fread($pipes[2], 1024);
|
||||
}
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
$status = proc_close($process);
|
||||
}
|
||||
|
||||
var_dump(array(
|
||||
"status" => $status,
|
||||
"stdout" => $stdout,
|
||||
"stderr" => $stderr,
|
||||
), strlen($stdout), strlen($stderr));
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--CLEAN--
|
||||
<?php
|
||||
$callee = dirname(__FILE__) . "/process_proc_open_bug51800_right2.php";
|
||||
unlink($callee);
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
["status"]=>
|
||||
int(0)
|
||||
["stdout"]=>
|
||||
string(1000000) "a%s"
|
||||
["stderr"]=>
|
||||
string(1000000) "b%s"
|
||||
}
|
||||
int(1000000)
|
||||
int(1000000)
|
||||
===DONE===
|
||||
|
71
ext/standard/tests/streams/proc_open_bug60120.phpt
Normal file
71
ext/standard/tests/streams/proc_open_bug60120.phpt
Normal file
@ -0,0 +1,71 @@
|
||||
--TEST--
|
||||
Bug #60120 proc_open hangs with stdin/out with 2048+ bytes
|
||||
--FILE--
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (substr(PHP_OS, 0, 3) == 'WIN') {
|
||||
$cmd = PHP_BINARY . ' -n -r "fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);"';
|
||||
} else {
|
||||
$cmd = PHP_BINARY . ' -n -r \'fwrite(STDOUT, $in = file_get_contents("php://stdin")); fwrite(STDERR, $in);\'';
|
||||
}
|
||||
$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
|
||||
$stdin = str_repeat('*', 1024 * 16) . '!';
|
||||
$stdin = str_repeat('*', 2049 );
|
||||
|
||||
$options = array_merge(array('suppress_errors' => true, 'binary_pipes' => true, 'bypass_shell' => false));
|
||||
$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options);
|
||||
|
||||
foreach ($pipes as $pipe) {
|
||||
stream_set_blocking($pipe, false);
|
||||
}
|
||||
$writePipes = array($pipes[0]);
|
||||
$stdinLen = strlen($stdin);
|
||||
$stdinOffset = 0;
|
||||
|
||||
unset($pipes[0]);
|
||||
|
||||
while ($pipes || $writePipes) {
|
||||
$r = $pipes;
|
||||
$w = $writePipes;
|
||||
$e = null;
|
||||
$n = stream_select($r, $w, $e, 60);
|
||||
|
||||
if (false === $n) {
|
||||
break;
|
||||
} elseif ($n === 0) {
|
||||
proc_terminate($process);
|
||||
|
||||
}
|
||||
if ($w) {
|
||||
$written = fwrite($writePipes[0], (binary)substr($stdin, $stdinOffset), 8192);
|
||||
if (false !== $written) {
|
||||
$stdinOffset += $written;
|
||||
}
|
||||
if ($stdinOffset >= $stdinLen) {
|
||||
fclose($writePipes[0]);
|
||||
$writePipes = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($r as $pipe) {
|
||||
$type = array_search($pipe, $pipes);
|
||||
$data = fread($pipe, 8192);
|
||||
var_dump($data);
|
||||
if (false === $data || feof($pipe)) {
|
||||
fclose($pipe);
|
||||
unset($pipes[$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
string(2049) "%s"
|
||||
string(2049) "%s"
|
||||
string(0) ""
|
||||
string(0) ""
|
||||
===DONE===
|
||||
|
70
ext/standard/tests/streams/proc_open_bug64438.phpt
Normal file
70
ext/standard/tests/streams/proc_open_bug64438.phpt
Normal file
@ -0,0 +1,70 @@
|
||||
--TEST--
|
||||
Bug #64438 proc_open hangs with stdin/out with 4097+ bytes
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (substr(PHP_OS, 0, 3) == 'WIN') {
|
||||
$cmd = PHP_BINARY . ' -n -r "fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);"';
|
||||
} else {
|
||||
$cmd = PHP_BINARY . ' -n -r \'fwrite(STDOUT, $in = file_get_contents("php://stdin")); fwrite(STDERR, $in);\'';
|
||||
}
|
||||
$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
|
||||
$stdin = str_repeat('*', 4097);
|
||||
|
||||
$options = array_merge(array('suppress_errors' => true, 'binary_pipes' => true, 'bypass_shell' => false));
|
||||
$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options);
|
||||
|
||||
foreach ($pipes as $pipe) {
|
||||
stream_set_blocking($pipe, false);
|
||||
}
|
||||
$writePipes = array($pipes[0]);
|
||||
$stdinLen = strlen($stdin);
|
||||
$stdinOffset = 0;
|
||||
|
||||
unset($pipes[0]);
|
||||
|
||||
while ($pipes || $writePipes) {
|
||||
$r = $pipes;
|
||||
$w = $writePipes;
|
||||
$e = null;
|
||||
$n = stream_select($r, $w, $e, 60);
|
||||
|
||||
if (false === $n) {
|
||||
break;
|
||||
} elseif ($n === 0) {
|
||||
proc_terminate($process);
|
||||
|
||||
}
|
||||
if ($w) {
|
||||
$written = fwrite($writePipes[0], (binary)substr($stdin, $stdinOffset), 8192);
|
||||
if (false !== $written) {
|
||||
$stdinOffset += $written;
|
||||
}
|
||||
if ($stdinOffset >= $stdinLen) {
|
||||
fclose($writePipes[0]);
|
||||
$writePipes = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($r as $pipe) {
|
||||
$type = array_search($pipe, $pipes);
|
||||
$data = fread($pipe, 8192);
|
||||
var_dump($data);
|
||||
if (false === $data || feof($pipe)) {
|
||||
fclose($pipe);
|
||||
unset($pipes[$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
string(4097) "%s"
|
||||
string(4097) "%s"
|
||||
string(0) ""
|
||||
string(0) ""
|
||||
===DONE===
|
||||
|
@ -18,8 +18,11 @@ if (substr(PHP_OS, 0, 3) == 'WIN') {
|
||||
/* setlocale() to set all available locales in the system and check the success count */
|
||||
echo "*** Testing setlocale() : usage variations ***\n";
|
||||
|
||||
function good_locale($locale) {
|
||||
return $locale !== 'tt_RU@iqtelif.UTF-8';
|
||||
function good_locale($locale) {
|
||||
/**
|
||||
* Note: no_NO is a bogus locale and should not be used, see https://bugzilla.redhat.com/971416
|
||||
**/
|
||||
return $locale !== 'tt_RU@iqtelif.UTF-8' && $locale !== 'no_NO.ISO-8859-1';
|
||||
}
|
||||
|
||||
/* Prototype : array list_system_locales( void )
|
||||
|
@ -66,6 +66,7 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sem_acquire, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, sem_identifier)
|
||||
ZEND_ARG_INFO(0, nowait)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_sem_release, 0, 0, 1)
|
||||
@ -298,11 +299,18 @@ PHP_FUNCTION(sem_get)
|
||||
static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire)
|
||||
{
|
||||
zval *arg_id;
|
||||
zend_bool nowait = 0;
|
||||
sysvsem_sem *sem_ptr;
|
||||
struct sembuf sop;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg_id) == FAILURE) {
|
||||
return;
|
||||
if (acquire) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &arg_id, &nowait) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg_id) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(sem_ptr, sysvsem_sem *, &arg_id, -1, "SysV semaphore", php_sysvsem_module.le_sem);
|
||||
@ -314,11 +322,13 @@ static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire)
|
||||
|
||||
sop.sem_num = SYSVSEM_SEM;
|
||||
sop.sem_op = acquire ? -1 : 1;
|
||||
sop.sem_flg = SEM_UNDO;
|
||||
sop.sem_flg = SEM_UNDO | (nowait ? IPC_NOWAIT : 0);
|
||||
|
||||
while (semop(sem_ptr->semid, &sop, 1) == -1) {
|
||||
if (errno != EINTR) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to %s key 0x%x: %s", acquire ? "acquire" : "release", sem_ptr->key, strerror(errno));
|
||||
if (errno != EAGAIN) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to %s key 0x%x: %s", acquire ? "acquire" : "release", sem_ptr->key, strerror(errno));
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
103
ext/sysvsem/tests/nowait.phpt
Normal file
103
ext/sysvsem/tests/nowait.phpt
Normal file
@ -0,0 +1,103 @@
|
||||
--TEST--
|
||||
sem_acquire with nowait
|
||||
--SKIPIF--
|
||||
<?php // vim600: ts=4 sw=4 syn=php fdm=marker
|
||||
if(!extension_loaded('sysvsem') || !extension_loaded('pcntl')) {
|
||||
die("skip sysvsem and pcntl required");
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$SEMKEY = ftok(__FILE__, 'P'); // Semaphore key
|
||||
|
||||
$pid = pcntl_fork();
|
||||
|
||||
if ($pid) {
|
||||
echo "Parent.\n";
|
||||
|
||||
pcntl_signal(SIGCHLD, SIG_IGN);
|
||||
|
||||
// Get semaphore
|
||||
$sem_id = sem_get($SEMKEY, 1);
|
||||
if ($sem_id === FALSE) {
|
||||
echo "P: fail to get semaphore";
|
||||
exit;
|
||||
}
|
||||
echo "P: got semaphore $sem_id.\n";
|
||||
|
||||
register_shutdown_function(function () use ($sem_id) {
|
||||
echo "P: cleanup.\n";
|
||||
sem_remove($sem_id);
|
||||
});
|
||||
|
||||
// Acquire semaphore
|
||||
if (! sem_acquire($sem_id)) {
|
||||
echo "P: fail to acquire semaphore $sem_id.\n";
|
||||
sem_remove($sem_id);
|
||||
exit;
|
||||
}
|
||||
echo "P: success acquire semaphore $sem_id.\n";
|
||||
|
||||
usleep(20000);
|
||||
|
||||
echo "P: releases.\n";
|
||||
sem_release($sem_id);
|
||||
|
||||
usleep(5000);
|
||||
|
||||
// Acquire semaphore
|
||||
if (! sem_acquire($sem_id)) {
|
||||
echo "P: fail to acquire semaphore $sem_id.\n";
|
||||
sem_remove($sem_id);
|
||||
exit;
|
||||
}
|
||||
echo "P: success acquire semaphore $sem_id.\n";
|
||||
|
||||
$status = null;
|
||||
pcntl_waitpid($pid, $status);
|
||||
|
||||
} else {
|
||||
usleep(10000);
|
||||
echo "Child.\n";
|
||||
|
||||
// Get semaphore
|
||||
$sem_id = sem_get($SEMKEY, 1);
|
||||
if ($sem_id === FALSE) {
|
||||
echo "C: fail to get semaphore";
|
||||
exit;
|
||||
}
|
||||
echo "C: got semaphore $sem_id.\n";
|
||||
|
||||
// Acquire semaphore
|
||||
if (! sem_acquire($sem_id)) {
|
||||
echo "C: fail to acquire semaphore $sem_id.\n";
|
||||
exit;
|
||||
}
|
||||
echo "C: success acquire semaphore $sem_id.\n";
|
||||
|
||||
echo "C: releases.\n";
|
||||
sem_release($sem_id);
|
||||
|
||||
usleep(10000);
|
||||
|
||||
// Acquire semaphore
|
||||
if (! sem_acquire($sem_id, true)) {
|
||||
echo "C: fail to acquire semaphore $sem_id.\n";
|
||||
exit;
|
||||
}
|
||||
echo "C: success acquire semaphore $sem_id.\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Parent.
|
||||
P: got semaphore Resource id #%i.
|
||||
P: success acquire semaphore Resource id #%i.
|
||||
Child.
|
||||
C: got semaphore Resource id #%i.
|
||||
P: releases.
|
||||
C: success acquire semaphore Resource id #%i.
|
||||
C: releases.
|
||||
P: success acquire semaphore Resource id #%i.
|
||||
C: fail to acquire semaphore Resource id #%i.
|
||||
P: cleanup.
|
@ -9,8 +9,8 @@ if(!extension_loaded('sysvsem') || !extension_loaded('sysvshm')) {
|
||||
--FILE--
|
||||
<?php
|
||||
$MEMSIZE = 512; // size of shared memory to allocate
|
||||
$SEMKEY = 1; // Semaphore key
|
||||
$SHMKEY = 2; // Shared memory key
|
||||
$SEMKEY = ftok(__FILE__, 'P'); // Semaphore key
|
||||
$SHMKEY = ftok(__FILE__, 'Q'); // Shared memory key
|
||||
|
||||
echo "Start.\n";
|
||||
// Get semaphore
|
||||
|
@ -241,7 +241,7 @@ typedef struct post_var_data {
|
||||
|
||||
static zend_bool add_post_var(zval *arr, post_var_data_t *var, zend_bool eof TSRMLS_DC)
|
||||
{
|
||||
char *ksep, *vsep;
|
||||
char *ksep, *vsep, *val;
|
||||
size_t klen, vlen;
|
||||
/* FIXME: string-size_t */
|
||||
unsigned int new_vlen;
|
||||
@ -272,15 +272,17 @@ static zend_bool add_post_var(zval *arr, post_var_data_t *var, zend_bool eof TSR
|
||||
vlen = 0;
|
||||
}
|
||||
|
||||
|
||||
php_url_decode(var->ptr, klen);
|
||||
|
||||
val = estrndup(ksep, vlen);
|
||||
if (vlen) {
|
||||
vlen = php_url_decode(ksep, vlen);
|
||||
vlen = php_url_decode(val, vlen);
|
||||
}
|
||||
|
||||
if (sapi_module.input_filter(PARSE_POST, var->ptr, &ksep, vlen, &new_vlen TSRMLS_CC)) {
|
||||
php_register_variable_safe(var->ptr, ksep, new_vlen, arr TSRMLS_CC);
|
||||
if (sapi_module.input_filter(PARSE_POST, var->ptr, &val, vlen, &new_vlen TSRMLS_CC)) {
|
||||
php_register_variable_safe(var->ptr, val, new_vlen, arr TSRMLS_CC);
|
||||
}
|
||||
efree(val);
|
||||
|
||||
var->ptr = vsep + (vsep != var->end);
|
||||
return 1;
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* edit configure.in to change version number */
|
||||
#define PHP_MAJOR_VERSION 5
|
||||
#define PHP_MINOR_VERSION 6
|
||||
#define PHP_RELEASE_VERSION 1
|
||||
#define PHP_RELEASE_VERSION 2
|
||||
#define PHP_EXTRA_VERSION "-dev"
|
||||
#define PHP_VERSION "5.6.1-dev"
|
||||
#define PHP_VERSION_ID 50601
|
||||
#define PHP_VERSION "5.6.2-dev"
|
||||
#define PHP_VERSION_ID 50602
|
||||
|
@ -342,6 +342,34 @@ static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count TSRMLS
|
||||
assert(data != NULL);
|
||||
|
||||
if (data->fd >= 0) {
|
||||
#ifdef PHP_WIN32
|
||||
php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
|
||||
|
||||
if (self->is_pipe || self->is_process_pipe) {
|
||||
HANDLE ph = (HANDLE)_get_osfhandle(data->fd);
|
||||
int retry = 0;
|
||||
DWORD avail_read = 0;
|
||||
|
||||
do {
|
||||
/* Look ahead to get the available data amount to read. Do the same
|
||||
as read() does, however not blocking forever. In case it failed,
|
||||
no data will be read (better than block). */
|
||||
if (!PeekNamedPipe(ph, NULL, 0, NULL, &avail_read, NULL)) {
|
||||
break;
|
||||
}
|
||||
/* If there's nothing to read, wait in 100ms periods. */
|
||||
if (0 == avail_read) {
|
||||
usleep(100000);
|
||||
}
|
||||
} while (0 == avail_read && retry++ < 320);
|
||||
|
||||
/* Reduce the required data amount to what is available, otherwise read()
|
||||
will block.*/
|
||||
if (avail_read < count) {
|
||||
count = avail_read;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ret = read(data->fd, buf, count);
|
||||
|
||||
if (ret == (size_t)-1 && errno == EINTR) {
|
||||
|
@ -1765,7 +1765,7 @@ mssql.secure_connection = Off
|
||||
;mbstring.encoding_translation = Off
|
||||
|
||||
; automatic encoding detection order.
|
||||
; "auto" detect order is changed accoding to mbstring.language
|
||||
; "auto" detect order is changed according to mbstring.language
|
||||
; http://php.net/mbstring.detect-order
|
||||
;mbstring.detect_order = auto
|
||||
|
||||
|
@ -1763,7 +1763,7 @@ mssql.secure_connection = Off
|
||||
;mbstring.encoding_translation = Off
|
||||
|
||||
; automatic encoding detection order.
|
||||
; "auto" detect order is changed accoding to mbstring.language
|
||||
; "auto" detect order is changed according to mbstring.language
|
||||
; http://php.net/mbstring.detect-order
|
||||
;mbstring.detect_order = auto
|
||||
|
||||
|
@ -1112,7 +1112,7 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
|
||||
|
||||
shutdown(req->fd, 1);
|
||||
/* read the last FCGI_STDIN header (it may be omitted) */
|
||||
recv(req->fd, &buf, sizeof(buf), 0);
|
||||
recv(req->fd, (char *)(&buf), sizeof(buf), 0);
|
||||
}
|
||||
closesocket(req->fd);
|
||||
}
|
||||
@ -1122,7 +1122,7 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
|
||||
|
||||
shutdown(req->fd, 1);
|
||||
/* read the last FCGI_STDIN header (it may be omitted) */
|
||||
recv(req->fd, &buf, sizeof(buf), 0);
|
||||
recv(req->fd, (char *)(&buf), sizeof(buf), 0);
|
||||
}
|
||||
close(req->fd);
|
||||
#endif
|
||||
|
@ -59,8 +59,6 @@ foreach ($codes as $key => $code) {
|
||||
|
||||
echo "\nDone\n";
|
||||
?>
|
||||
--XFAIL--
|
||||
https://bugs.php.net/bug.php?id=55496
|
||||
--EXPECTF--
|
||||
--------------
|
||||
Snippet no. 1:
|
||||
|
@ -1237,6 +1237,17 @@ static void init_request_info(TSRMLS_D)
|
||||
SG(request_info).request_uri = orig_script_name;
|
||||
}
|
||||
path_info[0] = old;
|
||||
} else if (apache_was_here && env_script_name) {
|
||||
/* Using mod_proxy_fcgi and ProxyPass, apache cannot set PATH_INFO
|
||||
* As we can extract PATH_INFO from PATH_TRANSLATED
|
||||
* it is probably also in SCRIPT_NAME and need to be removed
|
||||
*/
|
||||
int snlen = strlen(env_script_name);
|
||||
if (snlen>slen && !strcmp(env_script_name+snlen-slen, path_info)) {
|
||||
_sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
|
||||
env_script_name[snlen-slen] = 0;
|
||||
SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC);
|
||||
}
|
||||
|
@ -39,29 +39,6 @@ struct listening_socket_s {
|
||||
|
||||
static struct fpm_array_s sockets_list;
|
||||
|
||||
static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockaddr_in *addr) /* {{{ */
|
||||
{
|
||||
struct addrinfo *res;
|
||||
struct addrinfo hints;
|
||||
int ret;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
ret = getaddrinfo(node, service, &hints, &res);
|
||||
|
||||
if (ret != 0) {
|
||||
zlog(ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n",
|
||||
node, service ? ":" : "", service ? service : "",
|
||||
gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : "");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*addr = *(struct sockaddr_in *) res->ai_addr;
|
||||
freeaddrinfo(res);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 };
|
||||
|
||||
static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
|
||||
@ -98,14 +75,23 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void *fpm_get_in_addr(struct sockaddr *sa) /* {{{ */
|
||||
{
|
||||
if (sa->sa_family == AF_INET) {
|
||||
return &(((struct sockaddr_in*)sa)->sin_addr);
|
||||
}
|
||||
|
||||
return &(((struct sockaddr_in6*)sa)->sin6_addr);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op) /* {{{ */
|
||||
{
|
||||
if (key == NULL) {
|
||||
switch (type) {
|
||||
case FPM_AF_INET : {
|
||||
struct sockaddr_in *sa_in = (struct sockaddr_in *) sa;
|
||||
key = alloca(sizeof("xxx.xxx.xxx.xxx:ppppp"));
|
||||
sprintf(key, "%u.%u.%u.%u:%u", IPQUAD(&sa_in->sin_addr), (unsigned int) ntohs(sa_in->sin_port));
|
||||
key = alloca(INET6_ADDRSTRLEN);
|
||||
inet_ntop(sa->sa_family, fpm_get_in_addr(sa), key, sizeof key);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -254,11 +240,14 @@ enum fpm_address_domain fpm_sockets_domain_from_address(char *address) /* {{{ */
|
||||
|
||||
static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /* {{{ */
|
||||
{
|
||||
struct sockaddr_in sa_in;
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
char *dup_address = strdup(wp->config->listen_address);
|
||||
char *port_str = strchr(dup_address, ':');
|
||||
char *port_str = strrchr(dup_address, ':');
|
||||
char *addr = NULL;
|
||||
int addr_len;
|
||||
int port = 0;
|
||||
int sock;
|
||||
int status;
|
||||
|
||||
if (port_str) { /* this is host:port pair */
|
||||
*port_str++ = '\0';
|
||||
@ -274,23 +263,35 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sa_in, 0, sizeof(sa_in));
|
||||
|
||||
if (addr) {
|
||||
sa_in.sin_addr.s_addr = inet_addr(addr);
|
||||
if (sa_in.sin_addr.s_addr == INADDR_NONE) { /* do resolve */
|
||||
if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) {
|
||||
return -1;
|
||||
}
|
||||
zlog(ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr));
|
||||
// strip brackets from address for getaddrinfo
|
||||
if (addr != NULL) {
|
||||
addr_len = strlen(addr);
|
||||
if (addr[0] == '[' && addr[addr_len - 1] == ']') {
|
||||
addr[addr_len - 1] = '\0';
|
||||
addr++;
|
||||
}
|
||||
} else {
|
||||
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
sa_in.sin_family = AF_INET;
|
||||
sa_in.sin_port = htons(port);
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((status = getaddrinfo(addr, port_str, &hints, &servinfo)) != 0) {
|
||||
zlog(ZLOG_ERROR, "getaddrinfo: %s\n", gai_strerror(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(dup_address);
|
||||
return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in));
|
||||
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((sock = fpm_sockets_get_listening_socket(wp, p->ai_addr, p->ai_addrlen)) != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(servinfo);
|
||||
|
||||
return sock;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -45,10 +45,4 @@ static inline int fd_set_blocked(int fd, int blocked) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define IPQUAD(sin_addr) \
|
||||
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[0], \
|
||||
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[1], \
|
||||
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[2], \
|
||||
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[3]
|
||||
|
||||
#endif
|
||||
|
@ -152,6 +152,8 @@ group = @php_fpm_group@
|
||||
; Valid syntaxes are:
|
||||
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on
|
||||
; a specific port;
|
||||
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
|
||||
; a specific port;
|
||||
; 'port' - to listen on a TCP socket to all addresses on a
|
||||
; specific port;
|
||||
; '/path/to/unix/socket' - to listen on a unix socket.
|
||||
|
53
sapi/fpm/tests/003.phpt
Normal file
53
sapi/fpm/tests/003.phpt
Normal file
@ -0,0 +1,53 @@
|
||||
--TEST--
|
||||
FPM: Test IPv6 support
|
||||
--SKIPIF--
|
||||
<?php include "skipif.inc"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
include "include.inc";
|
||||
|
||||
$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
|
||||
|
||||
$cfg = <<<EOT
|
||||
[global]
|
||||
error_log = $logfile
|
||||
[unconfined]
|
||||
listen = [::1]:9000
|
||||
pm = dynamic
|
||||
pm.max_children = 5
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
EOT;
|
||||
|
||||
$fpm = run_fpm($cfg, $tail);
|
||||
if (is_resource($fpm)) {
|
||||
var_dump(fgets($tail));
|
||||
var_dump(fgets($tail));
|
||||
$i = 0;
|
||||
while (($i++ < 30) && !($fp = fsockopen('[::1]', 9000))) {
|
||||
usleep(10000);
|
||||
}
|
||||
if ($fp) {
|
||||
echo "Done\n";
|
||||
fclose($fp);
|
||||
}
|
||||
proc_terminate($fpm);
|
||||
stream_get_contents($tail);
|
||||
fclose($tail);
|
||||
proc_close($fpm);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
|
||||
"
|
||||
string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
|
||||
"
|
||||
Done
|
||||
--CLEAN--
|
||||
<?php
|
||||
$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
|
||||
@unlink($logfile);
|
||||
?>
|
@ -4,7 +4,6 @@ env:
|
||||
- PHP="PHP-5.4"
|
||||
- PHP="PHP-5.5"
|
||||
- PHP="PHP-5.6"
|
||||
- PHP="master"
|
||||
|
||||
before_script: ./travis/ci.sh
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
The interactive PHP debugger
|
||||
============================
|
||||
|
||||
Implemented as a SAPI module, phpdbg can excert complete control over the environment without impacting the functionality or performance of your code.
|
||||
Implemented as a SAPI module, phpdbg can exert complete control over the environment without impacting the functionality or performance of your code.
|
||||
|
||||
phpdbg aims to be a lightweight, powerful, easy to use debugging platform for PHP 5.4+
|
||||
|
||||
|
@ -1296,14 +1296,14 @@ phpdbg_main:
|
||||
|
||||
/* do not install sigint handlers for remote consoles */
|
||||
/* sending SIGINT then provides a decent way of shutting down the server */
|
||||
#if defined(ZEND_SIGNALS) && !defined(_WIN32)
|
||||
if (listen[0] < 0) {
|
||||
zend_try { zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); } zend_end_try();
|
||||
}
|
||||
#elif !defined(_WIN32)
|
||||
#ifndef _WIN32
|
||||
if (listen[0] < 0) {
|
||||
#endif
|
||||
#if defined(ZEND_SIGNALS) && !defined(_WIN32)
|
||||
zend_try { zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); } zend_end_try();
|
||||
#else
|
||||
signal(SIGINT, phpdbg_sigint_handler);
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user