mirror of
https://github.com/bdnugget/php-src.git
synced 2026-11-13 20:20:50 +00:00
Compare commits
73
Commits
php-7.4.16
...
php-7.4.19
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52e517a4b6 | ||
|
|
4c0231ebc3 | ||
|
|
d5cb73e7df | ||
|
|
8ab932d774 | ||
|
|
13389613fa | ||
|
|
f98f4875df | ||
|
|
b1680c5fe3 | ||
|
|
8cb114413f | ||
|
|
1e0f53278d | ||
|
|
d4f7e8cedc | ||
|
|
a1fdfa700b | ||
|
|
0a36d417e8 | ||
|
|
a04fac84e7 | ||
|
|
600402d986 | ||
|
|
340a06778c | ||
|
|
da3a807f22 | ||
|
|
454d297564 | ||
|
|
7a8ffcec7d | ||
|
|
29fa4d203a | ||
|
|
0826a54836 | ||
|
|
25f5a1b2e1 | ||
|
|
eebcfeb68e | ||
|
|
0a181ca27a | ||
|
|
9688071679 | ||
|
|
50f476591f | ||
|
|
39d8fc1edc | ||
|
|
206fd35a98 | ||
|
|
75cb678206 | ||
|
|
498eb8e052 | ||
|
|
688e56d0ac | ||
|
|
838951c2d6 | ||
|
|
bc7ea73da5 | ||
|
|
538f95b1b7 | ||
|
|
c483b59124 | ||
|
|
06bfada99b | ||
|
|
bccca0b53a | ||
|
|
4be867e910 | ||
|
|
a08847ab39 | ||
|
|
4adc08a403 | ||
|
|
5e4ee3d0bd | ||
|
|
eb1d1fe373 | ||
|
|
f448b0e6dd | ||
|
|
282355efd5 | ||
|
|
c93b461ad7 | ||
|
|
fc4cd598a2 | ||
|
|
703bbf5210 | ||
|
|
f901bec494 | ||
|
|
5787f91c55 | ||
|
|
8fc0bdfb0a | ||
|
|
797edd6211 | ||
|
|
e0e167e581 | ||
|
|
51e2015af3 | ||
|
|
71297a254b | ||
|
|
2c508c4d40 | ||
|
|
e857936518 | ||
|
|
988c3f9659 | ||
|
|
ae0585c98e | ||
|
|
a480bf8093 | ||
|
|
8309c04464 | ||
|
|
766f827e26 | ||
|
|
3ec37a74a2 | ||
|
|
78b0a85de6 | ||
|
|
67bb06cc9b | ||
|
|
729cd8bacd | ||
|
|
81396ea890 | ||
|
|
963e50c8c4 | ||
|
|
073b6ea818 | ||
|
|
d7c98ca1ac | ||
|
|
6dd85f83f7 | ||
|
|
84b6152842 | ||
|
|
9552cf6b84 | ||
|
|
2d858fbfb1 | ||
|
|
6d3d9104e6 |
No files matched your search
@@ -11,9 +11,7 @@ end
|
||||
|
||||
define ____executor_globals
|
||||
if basic_functions_module.zts
|
||||
if !$tsrm_ls
|
||||
set $tsrm_ls = ts_resource_ex(0, 0)
|
||||
end
|
||||
set $tsrm_ls = _tsrm_ls_cache
|
||||
set $eg = ((zend_executor_globals*) (*((void ***) $tsrm_ls))[executor_globals_id-1])
|
||||
set $cg = ((zend_compiler_globals*) (*((void ***) $tsrm_ls))[compiler_globals_id-1])
|
||||
set $eg_ptr = $eg
|
||||
|
||||
@@ -1,6 +1,90 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 2021, PHP 7.4.16
|
||||
06 May 2021, PHP 7.4.19
|
||||
|
||||
- PDO_pgsql:
|
||||
. Reverted bug fix for #80892 (PDO::PARAM_INT is treated the same as
|
||||
PDO::PARAM_STR). (Matteo)
|
||||
|
||||
29 Apr 2021, PHP 7.4.18
|
||||
|
||||
- Core:
|
||||
. Fixed bug #80781 (Error handler that throws ErrorException infinite loop).
|
||||
(Nikita)
|
||||
. Fixed bug #75776 (Flushing streams with compression filter is broken). (cmb)
|
||||
|
||||
- Dba:
|
||||
. Fixed bug #80817 (dba_popen() may cause segfault during RSHUTDOWN). (cmb)
|
||||
|
||||
- DOM:
|
||||
. Fixed bug #66783 (UAF when appending DOMDocument to element). (cmb)
|
||||
|
||||
- FPM:
|
||||
. Fixed bug #80024 (Duplication of info about inherited socket after pool
|
||||
removing). (Jakub Zelenka)
|
||||
|
||||
- FTP:
|
||||
. Fixed bug #80880 (SSL_read on shutdown, ftp/proc_open). (cmb, Jakub
|
||||
Zelenka)
|
||||
|
||||
- Imap:
|
||||
. Fixed bug #80710 (imap_mail_compose() header injection). (cmb, Stas)
|
||||
|
||||
- Intl:
|
||||
. Fixed bug #80763 (msgfmt_format() does not accept DateTime references).
|
||||
(cmb)
|
||||
|
||||
- LibXML:
|
||||
. Fixed bug #51903 (simplexml_load_file() doesn't use HTTP headers). (cmb)
|
||||
. Fixed bug #73533 (Invalid memory access in php_libxml_xmlCheckUTF8). (cmb)
|
||||
|
||||
- MySQLnd:
|
||||
. Fixed bug #80713 (SegFault when disabling ATTR_EMULATE_PREPARES and
|
||||
MySQL 8.0). (Nikita)
|
||||
. Fixed bug #80837 (Calling stmt_store_result after fetch doesn't throw an
|
||||
error). (Kamil Tekiela)
|
||||
|
||||
- Opcache:
|
||||
. Fixed bug #80805 (create simple class and get error in opcache.so). (Nikita)
|
||||
. Fixed bug #80950 (Variables become null in if statements). (Nikita)
|
||||
|
||||
- Pcntl:
|
||||
. Fixed bug #79812 (Potential integer overflow in pcntl_exec()). (cmb)
|
||||
|
||||
- PCRE:
|
||||
. Fixed bug #80866 (preg_split ignores limit flag when pattern with \K has
|
||||
0-width fullstring match). (Kamil Tekiela)
|
||||
|
||||
- PDO_ODBC:
|
||||
. Fixed bug #80783 (PDO ODBC truncates BLOB records at every 256th byte).
|
||||
(cmb)
|
||||
|
||||
- PDO_pgsql:
|
||||
. Fixed bug #80892 (PDO::PARAM_INT is treated the same as PDO::PARAM_STR).
|
||||
(Matteo)
|
||||
|
||||
- phpdbg:
|
||||
. Fixed bug #80757 (Exit code is 0 when could not open file). (Felipe)
|
||||
|
||||
- Session:
|
||||
. Fixed bug #80774 (session_name() problem with backslash). (cmb)
|
||||
. Fixed bug #80889 (Cannot set save handler when save_handler is invalid).
|
||||
(cmb)
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug #69668 (SOAP special XML characters in namespace URIs not
|
||||
encoded). (cmb)
|
||||
|
||||
- Standard:
|
||||
. Fixed bug #78719 (http wrapper silently ignores long Location headers).
|
||||
(cmb)
|
||||
. Fixed bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI). (cmb)
|
||||
. Fixed bug #80838 (HTTP wrapper waits for HTTP 1 response after HTTP 101).
|
||||
(manuelm)
|
||||
. Fixed bug #80915 (Taking a reference to $_SERVER hides its values from
|
||||
phpinfo()). (Rowan Tommins)
|
||||
|
||||
04 Mar 2021, php 7.4.16
|
||||
|
||||
- Core:
|
||||
. Fixed #80706 (mail(): Headers after Bcc headers may be ignored). (cmb)
|
||||
@@ -37,7 +121,7 @@ PHP NEWS
|
||||
. Fixed bug #80648 (Fix for bug 79296 should be based on runtime version).
|
||||
(cmb, Remi)
|
||||
|
||||
21 Jan 2021, PHP 7.4.15
|
||||
04 Feb 2021, PHP 7.4.15
|
||||
|
||||
- Core:
|
||||
. Fixed bug #80523 (bogus parse error on >4GB source code). (Nikita)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
HT iterator should be destroyed if array becomes empty during array_splice
|
||||
--FILE--
|
||||
<?php
|
||||
$a=[4];
|
||||
$i = 0;
|
||||
foreach ($a as &$r) {
|
||||
var_dump($r);
|
||||
$a = array_splice($a, 0);
|
||||
if (++$i == 2) break;
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
int(4)
|
||||
int(4)
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Bug #80781: Error handler that throws ErrorException infinite loop
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function handle(int $severity, string $message, string $file, int $line): bool {
|
||||
if((error_reporting() & $severity) !== 0) {
|
||||
throw new \ErrorException($message, 0, $severity, $file, $line);
|
||||
}
|
||||
|
||||
return true; // stfu operator
|
||||
}
|
||||
|
||||
set_error_handler('handle');
|
||||
|
||||
function getPlugin(string $plugin) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
$array = [];
|
||||
if (isset($array[$data]) or getPlugin($data)) {
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught ErrorException: Illegal offset type in isset or empty in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): handle(2, 'Illegal offset ...', %s, %d, Array)
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
+1
-1
@@ -1099,7 +1099,7 @@ static zend_always_inline void zend_mm_free_pages_ex(zend_mm_heap *heap, zend_mm
|
||||
/* this setting may be not accurate */
|
||||
chunk->free_tail = page_num;
|
||||
}
|
||||
if (free_chunk && chunk->free_pages == ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE) {
|
||||
if (free_chunk && chunk != heap->main_chunk && chunk->free_pages == ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE) {
|
||||
zend_mm_delete_chunk(heap, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -51,11 +51,11 @@
|
||||
# define ZEND_VM_FP_GLOBAL_REG "%r14"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "%r15"
|
||||
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
|
||||
# define ZEND_VM_FP_GLOBAL_REG "r28"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "r29"
|
||||
# define ZEND_VM_FP_GLOBAL_REG "r14"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "r15"
|
||||
# elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
|
||||
# define ZEND_VM_FP_GLOBAL_REG "r28"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "r29"
|
||||
# define ZEND_VM_FP_GLOBAL_REG "r14"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "r15"
|
||||
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__aarch64__)
|
||||
# define ZEND_VM_FP_GLOBAL_REG "x27"
|
||||
# define ZEND_VM_IP_GLOBAL_REG "x28"
|
||||
@@ -4555,6 +4555,7 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint
|
||||
if (check_exception) { \
|
||||
OPLINE = EX(opline) + (skip); \
|
||||
} else { \
|
||||
ZEND_ASSERT(!EG(exception)); \
|
||||
OPLINE = opline + (skip); \
|
||||
} \
|
||||
ZEND_VM_CONTINUE()
|
||||
|
||||
+1
-1
@@ -1630,10 +1630,10 @@ ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
|
||||
} else if (EXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) {
|
||||
goto free_ht;
|
||||
}
|
||||
zend_hash_iterators_remove(ht);
|
||||
SET_INCONSISTENT(HT_DESTROYED);
|
||||
efree(HT_GET_DATA_ADDR(ht));
|
||||
free_ht:
|
||||
zend_hash_iterators_remove(ht);
|
||||
FREE_HASHTABLE(ht);
|
||||
}
|
||||
|
||||
|
||||
@@ -6937,6 +6937,10 @@ ZEND_VM_C_LABEL(num_index_prop):
|
||||
ZEND_VM_C_GOTO(isset_again);
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
ZEND_VM_C_GOTO(isset_dim_obj_exit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
|
||||
@@ -6302,6 +6302,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -8496,6 +8500,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -10949,6 +10957,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -14985,6 +14997,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -16402,6 +16418,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -17689,6 +17709,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -41505,6 +41529,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -44950,6 +44978,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
@@ -50123,6 +50155,10 @@ num_index_prop:
|
||||
goto isset_again;
|
||||
} else {
|
||||
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
result = 0;
|
||||
goto isset_dim_obj_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(opline->extended_value & ZEND_ISEMPTY)) {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ parameters:
|
||||
jobs:
|
||||
- job: ${{ parameters.configurationName }}
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
vmImage: 'ubuntu-20.04'
|
||||
steps:
|
||||
- template: apt.yml
|
||||
- script: |
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice.
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
AC_PREREQ([2.68])
|
||||
AC_INIT([PHP],[7.4.16-dev],[https://bugs.php.net],[php],[https://www.php.net])
|
||||
AC_INIT([PHP],[7.4.19],[https://bugs.php.net],[php],[https://www.php.net])
|
||||
AC_CONFIG_SRCDIR([main/php_version.h])
|
||||
AC_CONFIG_AUX_DIR([build])
|
||||
AC_PRESERVE_HELP_ORDER
|
||||
@@ -568,7 +568,7 @@ dnl Fix for these systems is already included in GCC 7, but not on GCC 6.
|
||||
dnl
|
||||
dnl At least some versions of FreeBSD seem to have buggy ifunc support, see
|
||||
dnl bug #77284. Conservatively don't use ifuncs on FreeBSD.
|
||||
AS_CASE([$host_alias], [*-*-*android*|*-*-*uclibc*|*-*-*musl*|*freebsd*], [true], [
|
||||
AS_CASE([$host_alias], [*-*-*android*|*-*-*uclibc*|*-*-*musl*|*freebsd*|*openbsd*], [true], [
|
||||
AX_GCC_FUNC_ATTRIBUTE([ifunc])
|
||||
AX_GCC_FUNC_ATTRIBUTE([target])
|
||||
])
|
||||
|
||||
+10
-3
@@ -41,6 +41,7 @@ typedef struct _php_bz2_filter_data {
|
||||
enum strm_status status; /* Decompress option */
|
||||
unsigned int small_footprint : 1; /* Decompress option */
|
||||
unsigned int expect_concatenated : 1; /* Decompress option */
|
||||
unsigned int is_flushed : 1; /* only for compression */
|
||||
|
||||
int persistent;
|
||||
} php_bz2_filter_data;
|
||||
@@ -228,6 +229,8 @@ static php_stream_filter_status_t php_bz2_compress_filter(
|
||||
bucket = php_stream_bucket_make_writeable(buckets_in->head);
|
||||
|
||||
while (bin < bucket->buflen) {
|
||||
int flush_mode;
|
||||
|
||||
desired = bucket->buflen - bin;
|
||||
if (desired > data->inbuf_len) {
|
||||
desired = data->inbuf_len;
|
||||
@@ -235,7 +238,9 @@ static php_stream_filter_status_t php_bz2_compress_filter(
|
||||
memcpy(data->strm.next_in, bucket->buf + bin, desired);
|
||||
data->strm.avail_in = desired;
|
||||
|
||||
status = BZ2_bzCompress(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : (flags & PSFS_FLAG_FLUSH_INC ? BZ_FLUSH : BZ_RUN));
|
||||
flush_mode = flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : (flags & PSFS_FLAG_FLUSH_INC ? BZ_FLUSH : BZ_RUN);
|
||||
data->is_flushed = flush_mode != BZ_RUN;
|
||||
status = BZ2_bzCompress(&(data->strm), flush_mode);
|
||||
if (status != BZ_RUN_OK && status != BZ_FLUSH_OK && status != BZ_FINISH_OK) {
|
||||
/* Something bad happened */
|
||||
php_stream_bucket_delref(bucket);
|
||||
@@ -261,11 +266,12 @@ static php_stream_filter_status_t php_bz2_compress_filter(
|
||||
php_stream_bucket_delref(bucket);
|
||||
}
|
||||
|
||||
if (flags & PSFS_FLAG_FLUSH_CLOSE) {
|
||||
if (flags & PSFS_FLAG_FLUSH_CLOSE || ((flags & PSFS_FLAG_FLUSH_INC) && !data->is_flushed)) {
|
||||
/* Spit it out! */
|
||||
status = BZ_FINISH_OK;
|
||||
while (status == BZ_FINISH_OK) {
|
||||
status = BZ2_bzCompress(&(data->strm), BZ_FINISH);
|
||||
status = BZ2_bzCompress(&(data->strm), (flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : BZ_FLUSH));
|
||||
data->is_flushed = 1;
|
||||
if (data->strm.avail_out < data->outbuf_len) {
|
||||
size_t bucketlen = data->outbuf_len - data->strm.avail_out;
|
||||
|
||||
@@ -381,6 +387,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
|
||||
}
|
||||
|
||||
status = BZ2_bzCompressInit(&(data->strm), blockSize100k, 0, workFactor);
|
||||
data->is_flushed = 1;
|
||||
fops = &php_bz2_compress_ops;
|
||||
} else {
|
||||
status = BZ_DATA_ERROR;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Bug #75776 (Flushing streams with compression filter is broken)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('bz2')) die('skip bz2 extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$text = str_repeat('0123456789abcdef', 1000);
|
||||
|
||||
$temp = fopen('php://temp', 'r+');
|
||||
stream_filter_append($temp, 'bzip2.compress', STREAM_FILTER_WRITE);
|
||||
fwrite($temp, $text);
|
||||
|
||||
rewind($temp);
|
||||
|
||||
var_dump(bin2hex(stream_get_contents($temp)));
|
||||
var_dump(ftell($temp));
|
||||
|
||||
fclose($temp);
|
||||
?>
|
||||
--EXPECT--
|
||||
string(144) "425a68343141592653599fe7bbbf0001f389007fe03f002000902980026826aa80003ea9061520c6a41954833a9069520d6a41b54837a9071520e6a41d5483ba9079520f6a41f548"
|
||||
int(72)
|
||||
+2
-2
@@ -972,9 +972,9 @@ restart:
|
||||
zend_bool close_both;
|
||||
|
||||
close_both = (info->fp != info->lock.fp);
|
||||
php_stream_close(info->lock.fp);
|
||||
php_stream_free(info->lock.fp, persistent ? PHP_STREAM_FREE_CLOSE_PERSISTENT : PHP_STREAM_FREE_CLOSE);
|
||||
if (close_both) {
|
||||
php_stream_close(info->fp);
|
||||
php_stream_free(info->fp, persistent ? PHP_STREAM_FREE_CLOSE_PERSISTENT : PHP_STREAM_FREE_CLOSE);
|
||||
}
|
||||
info->fp = NULL;
|
||||
info->lock.fp = NULL;
|
||||
|
||||
+7
-3
@@ -1302,9 +1302,13 @@ int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child)
|
||||
{
|
||||
xmlNodePtr nodep;
|
||||
|
||||
if (parent == NULL || child == NULL || child->doc != parent->doc) {
|
||||
return SUCCESS;
|
||||
}
|
||||
if (parent == NULL || child == NULL || child->doc != parent->doc) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (child->type == XML_DOCUMENT_NODE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
nodep = parent;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ require_once __DIR__ .'/skipif.inc';
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$filename = __DIR__."/tmp_savehtmlfile".time().".html";
|
||||
$filename = __DIR__."/DOMDocument_saveHTMLFile_basic.html";
|
||||
$doc = new DOMDocument('1.0');
|
||||
$root = $doc->createElement('html');
|
||||
$root = $doc->appendChild($root);
|
||||
|
||||
@@ -9,7 +9,7 @@ require_once __DIR__ .'/skipif.inc';
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$filename = __DIR__."/tmp_savehtmlfile".time().".html";
|
||||
$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput.html";
|
||||
$doc = new DOMDocument('1.0');
|
||||
$doc->formatOutput = true;
|
||||
$root = $doc->createElement('html');
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Bug #66783 (UAF when appending DOMDocument to element)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('dom')) die('skip dom extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$doc = new DomDocument;
|
||||
$doc->loadXML('<root></root>');
|
||||
$e = $doc->createElement('e');
|
||||
try {
|
||||
$e->appendChild($doc);
|
||||
} catch (DOMException $ex) {
|
||||
echo $ex->getMessage(), PHP_EOL;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Hierarchy Request Error
|
||||
@@ -1931,6 +1931,12 @@ static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) {
|
||||
/* SSL wants a write. Really odd. Let's bail out. */
|
||||
done = 1;
|
||||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
/* most likely the peer closed the connection without
|
||||
sending a close_notify shutdown alert;
|
||||
bail out to avoid raising a spurious warning */
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
if ((sslerror = ERR_get_error())) {
|
||||
ERR_error_string_n(sslerror, buf, sizeof(buf));
|
||||
|
||||
@@ -3551,6 +3551,23 @@ PHP_FUNCTION(imap_fetch_overview)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool header_injection(zend_string *str, zend_bool adrlist)
|
||||
{
|
||||
char *p = ZSTR_VAL(str);
|
||||
|
||||
while ((p = strpbrk(p, "\r\n")) != NULL) {
|
||||
if (!(p[0] == '\r' && p[1] == '\n')
|
||||
/* adrlists do not support folding, but swallow trailing line breaks */
|
||||
&& !((adrlist && p[1] == '\0')
|
||||
/* other headers support folding */
|
||||
|| !adrlist && (p[1] == ' ' || p[1] == '\t'))) {
|
||||
return 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* {{{ proto string imap_mail_compose(array envelope, array body)
|
||||
Create a MIME message based on given envelope and body sections */
|
||||
PHP_FUNCTION(imap_mail_compose)
|
||||
@@ -3571,6 +3588,13 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
return;
|
||||
}
|
||||
|
||||
#define CHECK_HEADER_INJECTION(zstr, adrlist, header) \
|
||||
if (header_injection(zstr, adrlist)) { \
|
||||
php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
|
||||
RETVAL_FALSE; \
|
||||
goto done; \
|
||||
}
|
||||
|
||||
#define PHP_RFC822_PARSE_ADRLIST(target, value) \
|
||||
str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
|
||||
rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
|
||||
@@ -3579,46 +3603,57 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
env = mail_newenvelope();
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "remail");
|
||||
env->remail = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "return_path");
|
||||
PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "date", sizeof("date") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "date");
|
||||
env->date = (unsigned char*)cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "from", sizeof("from") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "from");
|
||||
PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "reply_to");
|
||||
PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "in_reply_to");
|
||||
env->in_reply_to = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "subject");
|
||||
env->subject = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "to", sizeof("to") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "to");
|
||||
PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "cc");
|
||||
PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "bcc");
|
||||
PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "message_id");
|
||||
env->message_id=cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
|
||||
@@ -3629,6 +3664,7 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pvalue), env_data) {
|
||||
custom_headers_param = mail_newbody_parameter();
|
||||
convert_to_string_ex(env_data);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(env_data), 0, "custom_headers");
|
||||
custom_headers_param->value = (char *) fs_get(Z_STRLEN_P(env_data) + 1);
|
||||
custom_headers_param->attribute = NULL;
|
||||
memcpy(custom_headers_param->value, Z_STRVAL_P(env_data), Z_STRLEN_P(env_data) + 1);
|
||||
@@ -3667,6 +3703,7 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
|
||||
tmp_param = mail_newbody_parameter();
|
||||
tmp_param->value = cpystr(Z_STRVAL_P(pvalue));
|
||||
tmp_param->attribute = cpystr("CHARSET");
|
||||
@@ -3679,9 +3716,11 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
SEPARATE_ARRAY(pvalue);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
|
||||
if (key == NULL) continue;
|
||||
CHECK_HEADER_INJECTION(key, 0, "body disposition key");
|
||||
disp_param = mail_newbody_parameter();
|
||||
disp_param->attribute = cpystr(ZSTR_VAL(key));
|
||||
convert_to_string_ex(disp_data);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
|
||||
disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
|
||||
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
|
||||
disp_param->next = tmp_param;
|
||||
@@ -3692,18 +3731,22 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
|
||||
bod->subtype = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
|
||||
bod->id = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
|
||||
bod->description = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
|
||||
bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
|
||||
memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
|
||||
}
|
||||
@@ -3713,9 +3756,11 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
SEPARATE_ARRAY(pvalue);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
|
||||
if (key == NULL) continue;
|
||||
CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
|
||||
disp_param = mail_newbody_parameter();
|
||||
disp_param->attribute = cpystr(ZSTR_VAL(key));
|
||||
convert_to_string_ex(disp_data);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
|
||||
disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
|
||||
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
|
||||
disp_param->next = tmp_param;
|
||||
@@ -3746,6 +3791,7 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
|
||||
bod->md5 = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
} else if (Z_TYPE_P(data) == IS_ARRAY && topbod->type == TYPEMULTIPART) {
|
||||
@@ -3778,6 +3824,7 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
|
||||
tmp_param = mail_newbody_parameter();
|
||||
tmp_param->value = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
|
||||
memcpy(tmp_param->value, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
|
||||
@@ -3791,9 +3838,11 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
SEPARATE_ARRAY(pvalue);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
|
||||
if (key == NULL) continue;
|
||||
CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
|
||||
disp_param = mail_newbody_parameter();
|
||||
disp_param->attribute = cpystr(ZSTR_VAL(key));
|
||||
convert_to_string_ex(disp_data);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
|
||||
disp_param->value = (char *)fs_get(Z_STRLEN_P(disp_data) + 1);
|
||||
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
|
||||
disp_param->next = tmp_param;
|
||||
@@ -3804,18 +3853,22 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
|
||||
bod->subtype = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
|
||||
bod->id = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
|
||||
bod->description = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
|
||||
bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
|
||||
memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
|
||||
}
|
||||
@@ -3825,9 +3878,11 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
SEPARATE_ARRAY(pvalue);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
|
||||
if (key == NULL) continue;
|
||||
CHECK_HEADER_INJECTION(key, 0, "body disposition key");
|
||||
disp_param = mail_newbody_parameter();
|
||||
disp_param->attribute = cpystr(ZSTR_VAL(key));
|
||||
convert_to_string_ex(disp_data);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
|
||||
disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
|
||||
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
|
||||
disp_param->next = tmp_param;
|
||||
@@ -3858,6 +3913,7 @@ PHP_FUNCTION(imap_mail_compose)
|
||||
}
|
||||
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
|
||||
convert_to_string_ex(pvalue);
|
||||
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
|
||||
bod->md5 = cpystr(Z_STRVAL_P(pvalue));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
Bug #80710 (imap_mail_compose() header injection) - MIME Splitting Attack
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("imap")) die("skip imap extension not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$envelope["from"]= "joe@example.com\n From : X-INJECTED";
|
||||
$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
|
||||
$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
|
||||
$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
|
||||
$envelope["x-remail"] = "bar@example.com\nFrom: X-INJECTED";
|
||||
$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
|
||||
|
||||
$part1["type"] = TYPEMULTIPART;
|
||||
$part1["subtype"] = "mixed";
|
||||
|
||||
$part2["type"] = TYPEAPPLICATION;
|
||||
$part2["encoding"] = ENCBINARY;
|
||||
$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
|
||||
$part2["description"] = "some file\nContent-Type: X-INJECTED";
|
||||
$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
|
||||
|
||||
$part3["type"] = TYPETEXT;
|
||||
$part3["subtype"] = "plain";
|
||||
$part3["description"] = "description3";
|
||||
$part3["contents.data"] = "contents.data3\n\n\n\t";
|
||||
|
||||
$body[1] = $part1;
|
||||
$body[2] = $part2;
|
||||
$body[3] = $part3;
|
||||
|
||||
echo imap_mail_compose($envelope, $body);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: imap_mail_compose(): header injection attempt in from in %s on line %d
|
||||
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
Bug #80710 (imap_mail_compose() header injection) - Remail
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("imap")) die("skip imap extension not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$envelope["from"]= "joe@example.com\n From : X-INJECTED";
|
||||
$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
|
||||
$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
|
||||
$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
|
||||
$envelope["remail"] = "X-INJECTED-REMAIL: X-INJECTED\nFrom: X-INJECTED-REMAIL-FROM"; //<--- Injected as first hdr
|
||||
$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
|
||||
|
||||
$part1["type"] = TYPEMULTIPART;
|
||||
$part1["subtype"] = "mixed";
|
||||
|
||||
$part2["type"] = TYPEAPPLICATION;
|
||||
$part2["encoding"] = ENCBINARY;
|
||||
$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
|
||||
$part2["description"] = "some file\nContent-Type: X-INJECTED";
|
||||
$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
|
||||
|
||||
$part3["type"] = TYPETEXT;
|
||||
$part3["subtype"] = "plain";
|
||||
$part3["description"] = "description3";
|
||||
$part3["contents.data"] = "contents.data3\n\n\n\t";
|
||||
|
||||
$body[1] = $part1;
|
||||
$body[2] = $part2;
|
||||
$body[3] = $part3;
|
||||
|
||||
echo imap_mail_compose($envelope, $body);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: imap_mail_compose(): header injection attempt in remail in %s on line %d
|
||||
@@ -175,6 +175,7 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func)
|
||||
return ZEND_NAN;
|
||||
}
|
||||
|
||||
try_again:
|
||||
switch (Z_TYPE_P(z)) {
|
||||
case IS_STRING:
|
||||
type = is_numeric_string(Z_STRVAL_P(z), Z_STRLEN_P(z), &lv, &rv, 0);
|
||||
@@ -227,6 +228,9 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func)
|
||||
efree(message);
|
||||
}
|
||||
break;
|
||||
case IS_REFERENCE:
|
||||
z = Z_REFVAL_P(z);
|
||||
goto try_again;
|
||||
default:
|
||||
spprintf(&message, 0, "%s: invalid PHP type for date", func);
|
||||
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #80763 (msgfmt_format() does not accept DateTime references)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('intl')) die('skip intl extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$today = new DateTime('2021-02-17 12:00:00');
|
||||
$formatter = new \MessageFormatter('en_US', 'Today is {today, date, full}.');
|
||||
$params = ['today' => $today];
|
||||
array_walk($params, fn() => 1);
|
||||
var_dump($formatter->format($params));
|
||||
?>
|
||||
--EXPECT--
|
||||
string(38) "Today is Wednesday, February 17, 2021."
|
||||
+49
-1
@@ -409,6 +409,54 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Check if there's been an external transport protocol with an encoding information */
|
||||
if (enc == XML_CHAR_ENCODING_NONE) {
|
||||
php_stream *s = (php_stream *) context;
|
||||
|
||||
if (Z_TYPE(s->wrapperdata) == IS_ARRAY) {
|
||||
zval *header;
|
||||
|
||||
ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) {
|
||||
const char buf[] = "Content-Type:";
|
||||
if (Z_TYPE_P(header) == IS_STRING &&
|
||||
!zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) {
|
||||
char *needle = estrdup("charset=");
|
||||
char *haystack = estrndup(Z_STRVAL_P(header), Z_STRLEN_P(header));
|
||||
char *encoding = php_stristr(haystack, needle, Z_STRLEN_P(header), sizeof("charset=")-1);
|
||||
|
||||
if (encoding) {
|
||||
char *end;
|
||||
|
||||
encoding += sizeof("charset=")-1;
|
||||
if (*encoding == '"') {
|
||||
encoding++;
|
||||
}
|
||||
end = strchr(encoding, ';');
|
||||
if (end == NULL) {
|
||||
end = encoding + strlen(encoding);
|
||||
}
|
||||
end--; /* end == encoding-1 isn't a buffer underrun */
|
||||
while (*end == ' ' || *end == '\t') {
|
||||
end--;
|
||||
}
|
||||
if (*end == '"') {
|
||||
end--;
|
||||
}
|
||||
if (encoding >= end) continue;
|
||||
*(end+1) = '\0';
|
||||
enc = xmlParseCharEncoding(encoding);
|
||||
if (enc <= XML_CHAR_ENCODING_NONE) {
|
||||
enc = XML_CHAR_ENCODING_NONE;
|
||||
}
|
||||
}
|
||||
efree(haystack);
|
||||
efree(needle);
|
||||
break; /* found content-type */
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate the Input buffer front-end. */
|
||||
ret = xmlAllocParserInputBuffer(enc);
|
||||
if (ret != NULL) {
|
||||
@@ -1134,7 +1182,7 @@ static PHP_FUNCTION(libxml_set_external_entity_loader)
|
||||
/* {{{ Common functions shared by extensions */
|
||||
int php_libxml_xmlCheckUTF8(const unsigned char *s)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
unsigned char c;
|
||||
|
||||
for (i = 0; (c = s[i++]);) {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
Bug #51903 (simplexml_load_file() doesn't use HTTP headers)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
|
||||
if (@!include "./ext/standard/tests/http/server.inc") die('skip server.inc not available');
|
||||
http_server_skipif('tcp://127.0.0.1:12342');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require "./ext/standard/tests/http/server.inc";
|
||||
$responses = [
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n"
|
||||
. "Content-Type: text/xml; charset=ISO-8859-1\r\n\r\n"
|
||||
. "<?xml version=\"1.0\"?>\n"
|
||||
. "<root>\xE4\xF6\xFC</root>\n",
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n"
|
||||
. "Content-Type: text/xml; charset=ISO-8859-1; foo=bar\r\n\r\n"
|
||||
. "<?xml version=\"1.0\"?>\n"
|
||||
. "<root>\xE4\xF6\xFC</root>\n",
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n"
|
||||
. "Content-Type: text/xml; charset=\"ISO-8859-1\" ; foo=bar\r\n\r\n"
|
||||
. "<?xml version=\"1.0\"?>\n"
|
||||
. "<root>\xE4\xF6\xFC</root>\n",
|
||||
];
|
||||
$pid = http_server('tcp://127.0.0.1:12342', $responses);
|
||||
|
||||
for ($i = 0; $i < count($responses); $i++) {
|
||||
$sxe = simplexml_load_file('http://127.0.0.1:12342/');
|
||||
echo "$sxe\n";
|
||||
}
|
||||
|
||||
http_server_kill($pid);
|
||||
?>
|
||||
--EXPECT--
|
||||
äöü
|
||||
äöü
|
||||
äöü
|
||||
@@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
Bug #80837 Calling stmt_store_result after fetch doesn't throw an error
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once 'skipif.inc';
|
||||
require_once 'skipifconnectfailure.inc';
|
||||
if (!defined('MYSQLI_STORE_RESULT_COPY_DATA')) die('skip requires mysqlnd');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once "connect.inc";
|
||||
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
|
||||
|
||||
$mysqli->query('DROP TABLE IF EXISTS test');
|
||||
$mysqli->query('CREATE TABLE test (b int)');
|
||||
$mysqli->query('INSERT INTO test VALUES (1),(2),(3)');
|
||||
|
||||
$statement = $mysqli->prepare("SELECT b FROM test");
|
||||
$statement->execute();
|
||||
$statement->bind_result($name);
|
||||
$statement->fetch();
|
||||
try {
|
||||
$statement->store_result();
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require_once "clean_table.inc";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Commands out of sync; you can't run this command now
|
||||
@@ -102,8 +102,8 @@ max_execution_time=240
|
||||
require_once('table.inc');
|
||||
|
||||
if (!$link = my_mysqli_connect($host, 'pamtest', 'pamtest', $db, $port, $socket)) {
|
||||
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
|
||||
$host, $user, $db, $port, $socket);
|
||||
printf("[001] Cannot connect to the server using host=%s, user=pamtest, passwd=pamtest dbname=%s, port=%s, socket=%s\n",
|
||||
$host, $db, $port, $socket);
|
||||
} else {
|
||||
|
||||
if (!$res = $link->query("SELECT id FROM test WHERE id = 1"))
|
||||
|
||||
@@ -92,7 +92,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
|
||||
|
||||
/* Nothing to store for UPSERT/LOAD DATA*/
|
||||
if (!mysqlnd_stmt_check_state(stmt)) {
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -1216,8 +1216,9 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
|
||||
DBG_RETURN(PASS);
|
||||
} else if (EODATA_MARKER == *p && packet->header.size < 8) {
|
||||
/* Premature EOF. That should be COM_FIELD_LIST. But we don't support COM_FIELD_LIST anymore, thus this should not happen */
|
||||
DBG_INF("Premature EOF. That should be COM_FIELD_LIST");
|
||||
DBG_RETURN(PASS);
|
||||
DBG_ERR("Premature EOF. That should be COM_FIELD_LIST");
|
||||
php_error_docref(NULL, E_WARNING, "Premature EOF in result field metadata");
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
meta = packet->metadata;
|
||||
|
||||
@@ -368,6 +368,10 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z
|
||||
return 0;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_bool may_be_refcounted(uint32_t type) {
|
||||
return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0;
|
||||
}
|
||||
|
||||
/* Returns whether the instruction has been DCEd */
|
||||
static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
|
||||
zend_ssa *ssa = ctx->ssa;
|
||||
@@ -379,16 +383,15 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
|
||||
}
|
||||
|
||||
/* We mark FREEs as dead, but they're only really dead if the destroyed var is dead */
|
||||
if (opline->opcode == ZEND_FREE
|
||||
&& (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
|
||||
if (opline->opcode == ZEND_FREE && may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
|
||||
&& !is_var_dead(ctx, ssa_op->op1_use)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
|
||||
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
|
||||
if (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)
|
||||
&& opline->opcode != ZEND_CASE) {
|
||||
if (may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
|
||||
&& opline->opcode != ZEND_CASE) {
|
||||
free_var = ssa_op->op1_use;
|
||||
free_var_type = opline->op1_type;
|
||||
}
|
||||
@@ -396,7 +399,7 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
|
||||
}
|
||||
if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) && !is_var_dead(ctx, ssa_op->op2_use)) {
|
||||
if (!try_remove_var_def(ctx, ssa_op->op2_use, ssa_op->op2_use_chain, opline)) {
|
||||
if (ssa->var_info[ssa_op->op2_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
|
||||
if (may_be_refcounted(ssa->var_info[ssa_op->op2_use].type)) {
|
||||
if (free_var >= 0) {
|
||||
// TODO: We can't free two vars. Keep instruction alive.
|
||||
zend_bitset_excl(ctx->instr_dead, opline - ctx->op_array->opcodes);
|
||||
@@ -503,6 +506,17 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
|
||||
ctx.phi_dead = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
|
||||
memset(ctx.phi_dead, 0xff, sizeof(zend_ulong) * ctx.phi_worklist_len);
|
||||
|
||||
/* Mark non-CV phis as live. Even if the result is unused, we generally cannot remove one
|
||||
* of the producing instructions, as it combines producing the result with control flow.
|
||||
* This can be made more precise if there are any cases where this is not the case. */
|
||||
FOREACH_PHI(phi) {
|
||||
if (phi->var >= op_array->last_var
|
||||
&& may_be_refcounted(ssa->var_info[phi->ssa_var].type)) {
|
||||
zend_bitset_excl(ctx.phi_dead, phi->ssa_var);
|
||||
add_phi_sources_to_worklists(&ctx, phi, 0);
|
||||
}
|
||||
} FOREACH_PHI_END();
|
||||
|
||||
/* Mark reacable instruction without side effects as dead */
|
||||
int b = ssa->cfg.blocks_count;
|
||||
while (b > 0) {
|
||||
|
||||
@@ -1040,7 +1040,7 @@ static const func_info_t func_infos[] = {
|
||||
F1("curl_version", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_ARRAY_OF_ARRAY),
|
||||
F0("curl_setopt", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
|
||||
F0("curl_setopt_array", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
|
||||
FN("curl_exec", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING),
|
||||
FN("curl_exec", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE | MAY_BE_STRING),
|
||||
F1("curl_getinfo", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY),
|
||||
F1("curl_error", MAY_BE_NULL | MAY_BE_STRING),
|
||||
F0("curl_errno", MAY_BE_NULL | MAY_BE_LONG),
|
||||
|
||||
@@ -1947,6 +1947,18 @@ static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset
|
||||
if (op->op2_def >= 0) {
|
||||
zend_bitset_incl(worklist, op->op2_def);
|
||||
}
|
||||
} else if (use + 1 < op_array->last
|
||||
&& op_array->opcodes[use + 1].opcode == ZEND_OP_DATA) {
|
||||
op++;
|
||||
if (op->result_def >= 0) {
|
||||
zend_bitset_incl(worklist, op->result_def);
|
||||
}
|
||||
if (op->op1_def >= 0) {
|
||||
zend_bitset_incl(worklist, op->op1_def);
|
||||
}
|
||||
if (op->op2_def >= 0) {
|
||||
zend_bitset_incl(worklist, op->op2_def);
|
||||
}
|
||||
}
|
||||
use = zend_ssa_next_use(ssa->ops, var, use);
|
||||
} while (use >= 0);
|
||||
@@ -2141,7 +2153,7 @@ static uint32_t assign_dim_result_type(
|
||||
|
||||
/* For binary ops that have compound assignment operators */
|
||||
static uint32_t binary_op_result_type(
|
||||
zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, uint32_t result_var,
|
||||
zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, int result_var,
|
||||
zend_long optimization_level) {
|
||||
uint32_t tmp = 0;
|
||||
uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
|
||||
@@ -2159,7 +2171,8 @@ static uint32_t binary_op_result_type(
|
||||
switch (opcode) {
|
||||
case ZEND_ADD:
|
||||
if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
|
||||
if (!ssa->var_info[result_var].has_range ||
|
||||
if (result_var < 0 ||
|
||||
!ssa->var_info[result_var].has_range ||
|
||||
ssa->var_info[result_var].range.underflow ||
|
||||
ssa->var_info[result_var].range.overflow) {
|
||||
/* may overflow */
|
||||
@@ -2185,7 +2198,8 @@ static uint32_t binary_op_result_type(
|
||||
case ZEND_SUB:
|
||||
case ZEND_MUL:
|
||||
if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
|
||||
if (!ssa->var_info[result_var].has_range ||
|
||||
if (result_var < 0 ||
|
||||
!ssa->var_info[result_var].has_range ||
|
||||
ssa->var_info[result_var].range.underflow ||
|
||||
ssa->var_info[result_var].range.overflow) {
|
||||
/* may overflow */
|
||||
@@ -2627,7 +2641,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
|
||||
}
|
||||
|
||||
tmp |= binary_op_result_type(
|
||||
ssa, opline->extended_value, t1, t2, ssa_ops[i].op1_def, optimization_level);
|
||||
ssa, opline->extended_value, t1, t2,
|
||||
opline->opcode == ZEND_ASSIGN_OP ? ssa_ops[i].op1_def : -1, optimization_level);
|
||||
if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) {
|
||||
tmp |= MAY_BE_RC1;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ void zend_shared_alloc_create_lock(void)
|
||||
{
|
||||
memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME));
|
||||
if (!memory_mutex) {
|
||||
zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex");
|
||||
zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex (error %u)", GetLastError());
|
||||
return;
|
||||
}
|
||||
ReleaseMutex(memory_mutex);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Bug #80805: create simple class and get error in opcache.so
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Test {
|
||||
public int $foo;
|
||||
public function __construct()
|
||||
{
|
||||
$this->foo = 2;
|
||||
}
|
||||
public function inc(): int
|
||||
{
|
||||
return $this->foo += 2;
|
||||
}
|
||||
}
|
||||
|
||||
$test = new Test();
|
||||
var_dump($test->foo);
|
||||
$test->inc();
|
||||
var_dump($test->foo);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(4)
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Incorrect DCE of FREE of COALESCE
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(?string $str) {
|
||||
$str ?? $str = '';
|
||||
return strlen($str);
|
||||
}
|
||||
|
||||
$foo = 'foo';
|
||||
$foo .= 'bar';
|
||||
var_dump(test($foo));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(6)
|
||||
@@ -3,14 +3,51 @@ Bug #62890 (default_socket_timeout=-1 causes connection to timeout)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('openssl')) die('skip openssl extension not available');
|
||||
if (getenv('SKIP_ONLINE_TESTS')) die('skip online test');
|
||||
if (!function_exists("proc_open")) die("skip no proc_open");
|
||||
?>
|
||||
--INI--
|
||||
default_socket_timeout=-1
|
||||
--FILE--
|
||||
<?php
|
||||
$clientCtx = stream_context_create(['ssl' => ['verify_peer' => false]]);
|
||||
var_dump((bool) file_get_contents('https://www.php.net', false, $clientCtx));
|
||||
$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug62890.pem.tmp';
|
||||
|
||||
$serverCode = <<<'CODE'
|
||||
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
|
||||
$ctx = stream_context_create(['ssl' => [
|
||||
'local_cert' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
$server = stream_socket_server('tls://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
|
||||
phpt_notify();
|
||||
@stream_socket_accept($server, 3);
|
||||
CODE;
|
||||
$serverCode = sprintf($serverCode, $certFile);
|
||||
|
||||
$clientCode = <<<'CODE'
|
||||
$flags = STREAM_CLIENT_CONNECT;
|
||||
$ctx = stream_context_create(['ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
phpt_wait();
|
||||
|
||||
$client = stream_socket_client("tls://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
|
||||
var_dump($client);
|
||||
CODE;
|
||||
|
||||
include 'CertificateGenerator.inc';
|
||||
$certificateGenerator = new CertificateGenerator();
|
||||
$certificateGenerator->saveNewCertAsFileWithKey('bug62890', $certFile);
|
||||
|
||||
include 'ServerClientTestCase.inc';
|
||||
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug62890.pem.tmp');
|
||||
?>
|
||||
--EXPECTF--
|
||||
resource(%d) of type (stream)
|
||||
@@ -3,7 +3,8 @@ Bug #80747: Providing RSA key size < 512 generates key that crash PHP
|
||||
--FILE--
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("openssl")) die("skip");
|
||||
if (!extension_loaded("openssl")) die("skip openssl not loaded");
|
||||
if (OPENSSL_VERSION_NUMBER < 0x10100000) die("skip OpenSSL >= v1.1.0 required");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
@@ -14,7 +14,8 @@ $serverCode = <<<'CODE'
|
||||
$serverUri = "ssl://127.0.0.1:64321";
|
||||
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
|
||||
$serverCtx = stream_context_create(['ssl' => [
|
||||
'local_cert' => '%s'
|
||||
'local_cert' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
|
||||
@@ -36,6 +37,7 @@ $clientCode = <<<'CODE'
|
||||
'cafile' => '%s',
|
||||
'peer_name' => '%s',
|
||||
'capture_session_meta' => true,
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
phpt_wait();
|
||||
|
||||
@@ -14,7 +14,8 @@ $serverCode = <<<'CODE'
|
||||
$serverUri = "ssl://127.0.0.1:64321";
|
||||
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
|
||||
$serverCtx = stream_context_create(['ssl' => [
|
||||
'local_cert' => '%s'
|
||||
'local_cert' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
|
||||
@@ -34,6 +35,7 @@ $clientCode = <<<'CODE'
|
||||
'verify_peer' => true,
|
||||
'cafile' => '%s',
|
||||
'peer_name' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
phpt_wait();
|
||||
|
||||
@@ -14,7 +14,8 @@ $serverCode = <<<'CODE'
|
||||
$serverUri = "ssl://127.0.0.1:64321";
|
||||
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
|
||||
$serverCtx = stream_context_create(['ssl' => [
|
||||
'local_cert' => '%s'
|
||||
'local_cert' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
|
||||
@@ -35,6 +36,7 @@ $clientCode = <<<'CODE'
|
||||
'verify_peer' => true,
|
||||
'cafile' => '%s',
|
||||
'peer_name' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
phpt_wait();
|
||||
|
||||
@@ -17,8 +17,9 @@ $serverCode = <<<'CODE'
|
||||
$serverCtx = stream_context_create(['ssl' => [
|
||||
'local_cert' => '%s',
|
||||
|
||||
// Only accept TLSv1.2 connections
|
||||
// Only accept TLSv1.0 and TLSv1.2 connections
|
||||
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER,
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
|
||||
@@ -39,6 +40,7 @@ $clientCode = <<<'CODE'
|
||||
'verify_peer' => true,
|
||||
'cafile' => '%s',
|
||||
'peer_name' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
phpt_wait();
|
||||
|
||||
@@ -16,6 +16,7 @@ $serverCode = <<<'CODE'
|
||||
$serverCtx = stream_context_create(['ssl' => [
|
||||
'local_cert' => '%s',
|
||||
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER,
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
|
||||
@@ -36,6 +37,7 @@ $clientCode = <<<'CODE'
|
||||
'verify_peer' => true,
|
||||
'cafile' => '%s',
|
||||
'peer_name' => '%s',
|
||||
'security_level' => 1,
|
||||
]]);
|
||||
|
||||
phpt_wait();
|
||||
|
||||
+3
-2
@@ -955,7 +955,7 @@ PHP_FUNCTION(pcntl_exec)
|
||||
int envc = 0, envi = 0;
|
||||
char **argv = NULL, **envp = NULL;
|
||||
char **current_arg, **pair;
|
||||
int pair_length;
|
||||
size_t pair_length;
|
||||
zend_string *key;
|
||||
char *path;
|
||||
size_t path_len;
|
||||
@@ -1015,8 +1015,9 @@ PHP_FUNCTION(pcntl_exec)
|
||||
}
|
||||
|
||||
/* Length of element + equal sign + length of key + null */
|
||||
ZEND_ASSERT(Z_STRLEN_P(element) < SIZE_MAX && ZSTR_LEN(key) < SIZE_MAX);
|
||||
*pair = safe_emalloc(Z_STRLEN_P(element) + 1, sizeof(char), ZSTR_LEN(key) + 1);
|
||||
pair_length = Z_STRLEN_P(element) + ZSTR_LEN(key) + 2;
|
||||
*pair = emalloc(pair_length);
|
||||
strlcpy(*pair, ZSTR_VAL(key), ZSTR_LEN(key) + 1);
|
||||
strlcat(*pair, "=", pair_length);
|
||||
strlcat(*pair, Z_STRVAL_P(element), pair_length);
|
||||
|
||||
@@ -9,6 +9,9 @@ pcntl: SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
// Clear mask
|
||||
pcntl_sigprocmask(SIG_SETMASK, array(), $prev);
|
||||
|
||||
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD,SIGTERM), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_BLOCK, array(SIGINT), $old);
|
||||
@@ -19,7 +22,9 @@ pcntl_sigprocmask(SIG_SETMASK, array(SIGINT), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_SETMASK, array(), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_SETMASK, array(), $old);
|
||||
|
||||
// Restore previous mask
|
||||
pcntl_sigprocmask(SIG_SETMASK, $prev, $old);
|
||||
var_dump(count($old));
|
||||
|
||||
?>
|
||||
|
||||
+5
-1
@@ -767,8 +767,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in
|
||||
zend_hash_add_ptr(&char_tables, _k, (void *)tables);
|
||||
zend_string_release(_k);
|
||||
}
|
||||
pcre2_set_character_tables(cctx, tables);
|
||||
}
|
||||
pcre2_set_character_tables(cctx, tables);
|
||||
|
||||
/* Set extra options for the compile context. */
|
||||
if (PHP_PCRE_DEFAULT_EXTRA_COPTIONS != extra_coptions) {
|
||||
@@ -2644,6 +2644,10 @@ matched:
|
||||
the match again at the same point. If this fails (picked up above) we
|
||||
advance to the next character. */
|
||||
if (start_offset == offsets[0]) {
|
||||
/* Get next piece if no limit or limit not yet reached and something matched*/
|
||||
if (limit_val != -1 && limit_val <= 1) {
|
||||
break;
|
||||
}
|
||||
count = pcre2_match(pce->re, (PCRE2_SPTR)subject, ZSTR_LEN(subject_str), start_offset,
|
||||
PCRE2_NO_UTF_CHECK | PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED, match_data, mctx);
|
||||
if (count >= 0) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Bug #80866 preg_split ignores limit flag when pattern with \K has 0-width fullstring match
|
||||
--FILE--
|
||||
<?php
|
||||
var_export(preg_split('~.{3}\K~', 'abcdefghijklm', 3));
|
||||
?>
|
||||
--EXPECT--
|
||||
array (
|
||||
0 => 'abc',
|
||||
1 => 'def',
|
||||
2 => 'ghijklm',
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Changing LC_CTYPE back to C
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!setlocale(LC_CTYPE, "de_DE", "de-DE")) die("skip requires de_DE locale");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(setlocale(LC_CTYPE, "de_DE", "de-DE") !== false);
|
||||
var_dump(preg_match('/\w/', "\xe4"));
|
||||
var_dump(setlocale(LC_CTYPE, "C") !== false);
|
||||
var_dump(preg_match('/\w/', "\xe4"));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
int(1)
|
||||
bool(true)
|
||||
int(0)
|
||||
@@ -652,6 +652,7 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
|
||||
/* if it is a column containing "long" data, perform late binding now */
|
||||
if (C->is_long) {
|
||||
SQLLEN orig_fetched_len = SQL_NULL_DATA;
|
||||
zend_ulong used = 0;
|
||||
char *buf;
|
||||
RETCODE rc;
|
||||
@@ -662,18 +663,20 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
|
||||
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data,
|
||||
256, &C->fetched_len);
|
||||
orig_fetched_len = C->fetched_len;
|
||||
|
||||
if (rc == SQL_SUCCESS) {
|
||||
if (rc == SQL_SUCCESS && C->fetched_len < 256) {
|
||||
/* all the data fit into our little buffer;
|
||||
* jump down to the generic bound data case */
|
||||
goto in_data;
|
||||
}
|
||||
|
||||
if (rc == SQL_SUCCESS_WITH_INFO) {
|
||||
if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) {
|
||||
/* this is a 'long column'
|
||||
|
||||
read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks
|
||||
in order into the output buffer
|
||||
in order into the output buffer; 255 bytes are an optimistic assumption, since the driver may assert
|
||||
more or less NUL bytes at the end; we cater to that later, if actual length information is available
|
||||
|
||||
this loop has to work whether or not SQLGetData() provides the total column length.
|
||||
calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read
|
||||
@@ -687,10 +690,17 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
|
||||
do {
|
||||
C->fetched_len = 0;
|
||||
/* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */
|
||||
rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, buf2, 256, &C->fetched_len);
|
||||
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, 256, &C->fetched_len);
|
||||
|
||||
/* adjust `used` in case we have length info from the driver */
|
||||
if (orig_fetched_len >= 0 && C->fetched_len >= 0) {
|
||||
SQLLEN fixed_used = orig_fetched_len - C->fetched_len;
|
||||
ZEND_ASSERT(fixed_used <= used + 1);
|
||||
used = fixed_used;
|
||||
}
|
||||
|
||||
/* resize output buffer and reassemble block */
|
||||
if (rc==SQL_SUCCESS_WITH_INFO) {
|
||||
if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > 255)) {
|
||||
/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
|
||||
states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size)
|
||||
(if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo_odbc')) die('skip pdo_odbc extension not available');
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("CREATE TABLE bug80783 (name IMAGE)");
|
||||
|
||||
$string = str_repeat("0123456789", 50);
|
||||
$db->exec("INSERT INTO bug80783 VALUES('$string')");
|
||||
|
||||
$stmt = $db->prepare("SELECT name FROM bug80783");
|
||||
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
|
||||
$stmt->execute();
|
||||
$stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
var_dump($data === bin2hex($string));
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("DROP TABLE bug80783");
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
@@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo_odbc')) die('skip pdo_odbc extension not available');
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("CREATE TABLE bug80783a (name NVARCHAR(MAX))");
|
||||
|
||||
$string = str_repeat("0123456789", 50);
|
||||
$db->exec("INSERT INTO bug80783a VALUES('$string')");
|
||||
|
||||
$stmt = $db->prepare("SELECT name FROM bug80783a");
|
||||
$stmt->setAttribute(PDO::ODBC_ATTR_ASSUME_UTF8, true);
|
||||
$stmt->bindColumn(1, $data, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
var_dump($data === $string);
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->exec("DROP TABLE bug80783a");
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
+12
-2
@@ -563,22 +563,32 @@ PHP_FUNCTION(posix_setegid)
|
||||
#ifdef HAVE_GETGROUPS
|
||||
PHP_FUNCTION(posix_getgroups)
|
||||
{
|
||||
gid_t gidlist[NGROUPS_MAX];
|
||||
gid_t *gidlist;
|
||||
int result;
|
||||
int i;
|
||||
|
||||
PHP_POSIX_NO_ARGS;
|
||||
|
||||
if ((result = getgroups(NGROUPS_MAX, gidlist)) < 0) {
|
||||
/* MacOS may return more than NGROUPS_MAX groups.
|
||||
* Fetch the actual number of groups and create an appropriate allocation. */
|
||||
if ((result = getgroups(0, NULL)) < 0) {
|
||||
POSIX_G(last_error) = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
gidlist = emalloc(sizeof(gid_t) * result);
|
||||
if ((result = getgroups(result, gidlist)) < 0) {
|
||||
POSIX_G(last_error) = errno;
|
||||
efree(gidlist);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
for (i=0; i<result; i++) {
|
||||
add_next_index_long(return_value, gidlist[i]);
|
||||
}
|
||||
efree(gidlist);
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
@@ -1534,6 +1534,11 @@ ZEND_METHOD(reflection_function, __construct)
|
||||
}
|
||||
}
|
||||
|
||||
if (intern->ptr) {
|
||||
zval_ptr_dtor(&intern->obj);
|
||||
zval_ptr_dtor(reflection_prop_name(object));
|
||||
}
|
||||
|
||||
ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
|
||||
intern->ptr = fptr;
|
||||
intern->ref_type = REF_TYPE_FUNCTION;
|
||||
@@ -2073,6 +2078,10 @@ ZEND_METHOD(reflection_generator, __construct)
|
||||
return;
|
||||
}
|
||||
|
||||
if (intern->ce) {
|
||||
zval_ptr_dtor(&intern->obj);
|
||||
}
|
||||
|
||||
intern->ref_type = REF_TYPE_GENERATOR;
|
||||
Z_ADDREF_P(generator);
|
||||
ZVAL_OBJ(&intern->obj, Z_OBJ_P(generator));
|
||||
|
||||
+29
-27
@@ -1261,13 +1261,11 @@ static void php_session_remove_cookie(void) {
|
||||
zend_llist_element *next;
|
||||
zend_llist_element *current;
|
||||
char *session_cookie;
|
||||
zend_string *e_session_name;
|
||||
size_t session_cookie_len;
|
||||
size_t len = sizeof("Set-Cookie")-1;
|
||||
|
||||
e_session_name = php_url_encode(PS(session_name), strlen(PS(session_name)));
|
||||
spprintf(&session_cookie, 0, "Set-Cookie: %s=", ZSTR_VAL(e_session_name));
|
||||
zend_string_free(e_session_name);
|
||||
ZEND_ASSERT(strpbrk(PS(session_name), "=,; \t\r\n\013\014") == NULL);
|
||||
spprintf(&session_cookie, 0, "Set-Cookie: %s=", PS(session_name));
|
||||
|
||||
session_cookie_len = strlen(session_cookie);
|
||||
current = l->head;
|
||||
@@ -1299,7 +1297,7 @@ static int php_session_send_cookie(void) /* {{{ */
|
||||
{
|
||||
smart_str ncookie = {0};
|
||||
zend_string *date_fmt = NULL;
|
||||
zend_string *e_session_name, *e_id;
|
||||
zend_string *e_id;
|
||||
|
||||
if (SG(headers_sent)) {
|
||||
const char *output_start_filename = php_output_get_start_filename();
|
||||
@@ -1313,16 +1311,20 @@ static int php_session_send_cookie(void) /* {{{ */
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* URL encode session_name and id because they might be user supplied */
|
||||
e_session_name = php_url_encode(PS(session_name), strlen(PS(session_name)));
|
||||
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
|
||||
if (strpbrk(PS(session_name), "=,; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
|
||||
php_error_docref(NULL, E_WARNING, "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* URL encode id because it might be user supplied */
|
||||
e_id = php_url_encode(ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)));
|
||||
|
||||
smart_str_appendl(&ncookie, "Set-Cookie: ", sizeof("Set-Cookie: ")-1);
|
||||
smart_str_appendl(&ncookie, ZSTR_VAL(e_session_name), ZSTR_LEN(e_session_name));
|
||||
smart_str_appendl(&ncookie, PS(session_name), strlen(PS(session_name)));
|
||||
smart_str_appendc(&ncookie, '=');
|
||||
smart_str_appendl(&ncookie, ZSTR_VAL(e_id), ZSTR_LEN(e_id));
|
||||
|
||||
zend_string_release_ex(e_session_name, 0);
|
||||
zend_string_release_ex(e_id, 0);
|
||||
|
||||
if (PS(cookie_lifetime) > 0) {
|
||||
@@ -1921,13 +1923,24 @@ static PHP_FUNCTION(session_module_name)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline void set_user_save_handler_ini(void) {
|
||||
zend_string *ini_name, *ini_val;
|
||||
|
||||
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
|
||||
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
|
||||
PS(set_handler) = 1;
|
||||
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
||||
PS(set_handler) = 0;
|
||||
zend_string_release_ex(ini_val, 0);
|
||||
zend_string_release_ex(ini_name, 0);
|
||||
}
|
||||
|
||||
/* {{{ proto bool session_set_save_handler(string open, string close, string read, string write, string destroy, string gc, string create_sid)
|
||||
Sets user-level functions */
|
||||
static PHP_FUNCTION(session_set_save_handler)
|
||||
{
|
||||
zval *args = NULL;
|
||||
int i, num_args, argc = ZEND_NUM_ARGS();
|
||||
zend_string *ini_name, *ini_val;
|
||||
|
||||
if (PS(session_status) == php_session_active) {
|
||||
php_error_docref(NULL, E_WARNING, "Cannot change save handler when session is active");
|
||||
@@ -2029,14 +2042,8 @@ static PHP_FUNCTION(session_set_save_handler)
|
||||
remove_user_shutdown_function("session_shutdown", sizeof("session_shutdown") - 1);
|
||||
}
|
||||
|
||||
if (PS(mod) && PS(session_status) != php_session_active && PS(mod) != &ps_mod_user) {
|
||||
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
|
||||
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
|
||||
PS(set_handler) = 1;
|
||||
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
||||
PS(set_handler) = 0;
|
||||
zend_string_release_ex(ini_val, 0);
|
||||
zend_string_release_ex(ini_name, 0);
|
||||
if (PS(session_status) != php_session_active && (!PS(mod) || PS(mod) != &ps_mod_user)) {
|
||||
set_user_save_handler_ini();
|
||||
}
|
||||
|
||||
RETURN_TRUE;
|
||||
@@ -2064,14 +2071,8 @@ static PHP_FUNCTION(session_set_save_handler)
|
||||
}
|
||||
}
|
||||
|
||||
if (PS(mod) && PS(mod) != &ps_mod_user) {
|
||||
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
|
||||
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
|
||||
PS(set_handler) = 1;
|
||||
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
||||
PS(set_handler) = 0;
|
||||
zend_string_release_ex(ini_val, 0);
|
||||
zend_string_release_ex(ini_name, 0);
|
||||
if (!PS(mod) || PS(mod) != &ps_mod_user) {
|
||||
set_user_save_handler_ini();
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
@@ -2854,7 +2855,8 @@ static int php_rinit_session(zend_bool auto_start) /* {{{ */
|
||||
{
|
||||
php_rinit_session_globals();
|
||||
|
||||
if (PS(mod) == NULL) {
|
||||
PS(mod) = NULL;
|
||||
{
|
||||
char *value;
|
||||
|
||||
value = zend_ini_string("session.save_handler", sizeof("session.save_handler") - 1, 0);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Bug #80774 (session_name() problem with backslash)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('session')) die("skip session extension not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
session_name("foo\\bar");
|
||||
session_id('12345');
|
||||
session_start();
|
||||
?>
|
||||
--EXPECTHEADERS--
|
||||
Set-Cookie: foo\bar=12345; path=/
|
||||
--EXPECT--
|
||||
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
Bug #80889 (Cannot set save handler when save_handler is invalid)
|
||||
--SKIPIF--
|
||||
<?php include('skipif.inc'); ?>
|
||||
--INI--
|
||||
session.save_handler=whatever
|
||||
--FILE--
|
||||
<?php
|
||||
class DummyHandler implements SessionHandlerInterface {
|
||||
public function open($savePath, $sessionName) {
|
||||
return true;
|
||||
}
|
||||
public function close() {
|
||||
return true;
|
||||
}
|
||||
public function read($id) {
|
||||
return '';
|
||||
}
|
||||
public function write($id, $data) {
|
||||
return true;
|
||||
}
|
||||
public function destroy($id) {
|
||||
return true;
|
||||
}
|
||||
public function gc($maxlifetime) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$initHandler = ini_get('session.save_handler');
|
||||
session_set_save_handler(new DummyHandler());
|
||||
$setHandler = ini_get('session.save_handler');
|
||||
var_dump($initHandler, $setHandler);
|
||||
?>
|
||||
--EXPECT--
|
||||
string(8) "whatever"
|
||||
string(4) "user"
|
||||
@@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
Bug #80889 (Cannot set save handler when save_handler is invalid)
|
||||
--SKIPIF--
|
||||
<?php include('skipif.inc'); ?>
|
||||
--INI--
|
||||
session.save_handler=whatever
|
||||
--FILE--
|
||||
<?php
|
||||
$initHandler = ini_get('session.save_handler');
|
||||
session_set_save_handler(
|
||||
function ($savePath, $sessionName) {
|
||||
return true;
|
||||
},
|
||||
function () {
|
||||
return true;
|
||||
},
|
||||
function ($id) {
|
||||
return '';
|
||||
},
|
||||
function ($id, $data) {
|
||||
return true;
|
||||
},
|
||||
function ($id) {
|
||||
return true;
|
||||
},
|
||||
function ($maxlifetime) {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
$setHandler = ini_get('session.save_handler');
|
||||
var_dump($initHandler, $setHandler);
|
||||
?>
|
||||
--EXPECT--
|
||||
string(8) "whatever"
|
||||
string(4) "user"
|
||||
@@ -48,6 +48,8 @@ string(9) "PHPSESSID"
|
||||
bool(true)
|
||||
string(9) "PHPSESSID"
|
||||
string(9) "PHPSESSID"
|
||||
|
||||
Warning: session_start(): session.name cannot contain any of the following '=,; \t\r\n\013\014' in %s on line %d
|
||||
bool(true)
|
||||
string(1) " "
|
||||
bool(true)
|
||||
@@ -55,6 +57,8 @@ string(1) " "
|
||||
|
||||
Warning: session_name(): session.name cannot be a numeric or empty '' in %s on line %d
|
||||
string(1) " "
|
||||
|
||||
Warning: session_start(): session.name cannot contain any of the following '=,; \t\r\n\013\014' in %s on line %d
|
||||
bool(true)
|
||||
string(1) " "
|
||||
bool(true)
|
||||
|
||||
@@ -3381,6 +3381,7 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
|
||||
} else {
|
||||
smart_str prefix = {0};
|
||||
int num = ++SOAP_GLOBAL(cur_uniq_ns);
|
||||
xmlChar *enc_ns;
|
||||
|
||||
while (1) {
|
||||
smart_str_appendl(&prefix, "ns", 2);
|
||||
@@ -3394,7 +3395,9 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
|
||||
num = ++SOAP_GLOBAL(cur_uniq_ns);
|
||||
}
|
||||
|
||||
xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
|
||||
enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
|
||||
xmlns = xmlNewNs(node->doc->children, enc_ns, BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
|
||||
xmlFree(enc_ns);
|
||||
smart_str_free(&prefix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Bug #69668 (SOAP: special XML characters in namespace URIs not encoded)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once('skipif.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
class MySoapClient extends SoapClient {
|
||||
public function __doRequest($request, $location, $action, $version, $one_way = 0) {
|
||||
echo $request, PHP_EOL;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
$client = new MySoapClient(__DIR__ . '/bug69668.wsdl', [
|
||||
'trace' => true,
|
||||
'exceptions' => true,
|
||||
'cache_wsdl' => WSDL_CACHE_NONE,
|
||||
]);
|
||||
|
||||
$client->test();
|
||||
?>
|
||||
--EXPECT--
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost/69668.php?a=a&b=b" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:test/></SOAP-ENV:Body></SOAP-ENV:Envelope>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://localhost/69668.php?a=a&b=b" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" name="TestService" targetNamespace="http://localhost/69668.php?a=a&b=b">
|
||||
<types>
|
||||
<xsd:schema targetNamespace="http://localhost/69668.php?a=a&b=b" />
|
||||
</types>
|
||||
<portType name="TestServicePort">
|
||||
<operation name="test">
|
||||
<documentation>test</documentation>
|
||||
<input message="tns:testIn" />
|
||||
<output message="tns:testOut" />
|
||||
</operation>
|
||||
</portType>
|
||||
<binding name="TestServiceBinding" type="tns:TestServicePort">
|
||||
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
|
||||
<operation name="test">
|
||||
<soap:operation soapAction="http://localhost/69668.php?a=a&b=b#test" />
|
||||
<input>
|
||||
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/69668.php?a=a&b=b" />
|
||||
</input>
|
||||
<output>
|
||||
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/69668.php?a=a&b=b" />
|
||||
</output>
|
||||
</operation>
|
||||
</binding>
|
||||
<service name="TestServiceService">
|
||||
<port name="TestServicePort" binding="tns:TestServiceBinding">
|
||||
<soap:address location="http://localhost/69668.php?a=a&b=b" />
|
||||
</port>
|
||||
</service>
|
||||
<message name="testIn" />
|
||||
<message name="testOut">
|
||||
<part name="return" type="xsd:string" />
|
||||
</message>
|
||||
</definitions>
|
||||
@@ -680,7 +680,7 @@ finish:
|
||||
/* status codes of 1xx are "informational", and will be followed by a real response
|
||||
* e.g "100 Continue". RFC 7231 states that unexpected 1xx status MUST be parsed,
|
||||
* and MAY be ignored. As such, we need to skip ahead to the "real" status*/
|
||||
if (response_code >= 100 && response_code < 200) {
|
||||
if (response_code >= 100 && response_code < 200 && response_code != 101) {
|
||||
/* consume lines until we find a line starting 'HTTP/1' */
|
||||
while (
|
||||
!php_stream_eof(stream)
|
||||
@@ -732,24 +732,16 @@ finish:
|
||||
|
||||
/* read past HTTP headers */
|
||||
|
||||
http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE);
|
||||
|
||||
while (!php_stream_eof(stream)) {
|
||||
size_t http_header_line_length;
|
||||
|
||||
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') {
|
||||
if (http_header_line != NULL) {
|
||||
efree(http_header_line);
|
||||
}
|
||||
if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length)) && *http_header_line != '\n' && *http_header_line != '\r') {
|
||||
char *e = http_header_line + http_header_line_length - 1;
|
||||
char *http_header_value;
|
||||
if (*e != '\n') {
|
||||
do { /* partial header */
|
||||
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) {
|
||||
php_stream_wrapper_log_error(wrapper, options, "Failed to read HTTP headers");
|
||||
goto out;
|
||||
}
|
||||
e = http_header_line + http_header_line_length - 1;
|
||||
} while (*e != '\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
while (e >= http_header_line && (*e == '\n' || *e == '\r')) {
|
||||
e--;
|
||||
}
|
||||
|
||||
+2
-2
@@ -176,7 +176,7 @@ static ZEND_COLD void php_print_gpcse_array(char *name, uint32_t name_length)
|
||||
key = zend_string_init(name, name_length, 0);
|
||||
zend_is_auto_global(key);
|
||||
|
||||
if ((data = zend_hash_find(&EG(symbol_table), key)) != NULL && (Z_TYPE_P(data) == IS_ARRAY)) {
|
||||
if ((data = zend_hash_find_deref(&EG(symbol_table), key)) != NULL && (Z_TYPE_P(data) == IS_ARRAY)) {
|
||||
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(data), num_key, string_key, tmp) {
|
||||
if (!sapi_module.phpinfo_as_text) {
|
||||
php_info_print("<tr>");
|
||||
@@ -1000,7 +1000,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag)
|
||||
}
|
||||
|
||||
|
||||
if ((flag & PHP_INFO_CREDITS) && !sapi_module.phpinfo_as_text) {
|
||||
if (flag & PHP_INFO_CREDITS) {
|
||||
php_info_print_hr();
|
||||
php_print_credits(PHP_CREDITS_ALL & ~PHP_CREDITS_FULLPAGE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Bug #80915: Taking a reference to $_SERVER hides its values from phpinfo()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$_ENV = [];
|
||||
$_SERVER = [ 'test' => 'test' ];
|
||||
|
||||
$reference =& $_SERVER;
|
||||
|
||||
phpinfo(INFO_VARIABLES);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
phpinfo()
|
||||
|
||||
PHP Variables
|
||||
|
||||
Variable => Value
|
||||
$_SERVER['test'] => test
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI)
|
||||
--FILE--
|
||||
<?php
|
||||
ob_start();
|
||||
phpinfo(INFO_CREDITS);
|
||||
$info = ob_get_clean();
|
||||
|
||||
ob_start();
|
||||
phpcredits();
|
||||
$credits = ob_get_clean();
|
||||
|
||||
var_dump(strpos($info, $credits) !== false);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Bug #78719 (http wrapper silently ignores long Location headers)
|
||||
--SKIPIF--
|
||||
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
|
||||
--INI--
|
||||
allow_url_fopen=1
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
$url = str_repeat('*', 2000);
|
||||
$responses = array(
|
||||
"data://text/plain,HTTP/1.0 302 Ok\r\nLocation: $url\r\n\r\nBody",
|
||||
);
|
||||
$pid = http_server("tcp://127.0.0.1:12342", $responses, $output);
|
||||
|
||||
$context = stream_context_create(['http' => ['follow_location' => 0]]);
|
||||
$stream = fopen('http://127.0.0.1:12342/', 'r', false, $context);
|
||||
var_dump(stream_get_contents($stream));
|
||||
var_dump(stream_get_meta_data($stream)['wrapper_data'][1] === "Location: $url");
|
||||
|
||||
http_server_kill($pid);
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(4) "Body"
|
||||
bool(true)
|
||||
@@ -0,0 +1,41 @@
|
||||
--TEST--
|
||||
Bug #80838 (HTTP wrapper waits for HTTP 1 response after HTTP 101)
|
||||
--INI--
|
||||
allow_url_fopen=1
|
||||
--SKIPIF--
|
||||
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'server.inc';
|
||||
|
||||
$responses = [
|
||||
"data://text/plain,HTTP/1.1 101 Switching Protocols\r\nHeader1: Value1\r\nHeader2: Value2\r\n\r\n"
|
||||
. "Hello from another protocol"
|
||||
];
|
||||
|
||||
$pid = http_server('tcp://127.0.0.1:12342', $responses);
|
||||
|
||||
$options = [
|
||||
'http' => [
|
||||
'ignore_errors' => true
|
||||
],
|
||||
];
|
||||
|
||||
$ctx = stream_context_create($options);
|
||||
|
||||
$fd = fopen('http://127.0.0.1:12342/', 'rb', false, $ctx);
|
||||
fclose($fd);
|
||||
var_dump($http_response_header);
|
||||
|
||||
http_server_kill($pid);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(32) "HTTP/1.1 101 Switching Protocols"
|
||||
[1]=>
|
||||
string(15) "Header1: Value1"
|
||||
[2]=>
|
||||
string(15) "Header2: Value2"
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
--TEST--
|
||||
Bug #80751 (Comma in recipient name breaks email delivery)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only test');
|
||||
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
|
||||
require_once __DIR__ . '/mail_skipif.inc';
|
||||
?>
|
||||
--INI--
|
||||
SMTP=localhost
|
||||
smtp_port=25
|
||||
--FILE--
|
||||
<?php
|
||||
require_once __DIR__ . '/mail_include.inc';
|
||||
|
||||
function find_and_delete_message($username, $subject) {
|
||||
global $default_mailbox, $password;
|
||||
|
||||
$imap_stream = imap_open($default_mailbox, $username, $password);
|
||||
if ($imap_stream === false) {
|
||||
die("Cannot connect to IMAP server $server: " . imap_last_error() . "\n");
|
||||
}
|
||||
|
||||
$found = false;
|
||||
$repeat_count = 20; // we will repeat a max of 20 times
|
||||
while (!$found && $repeat_count > 0) {
|
||||
// sleep for a while to allow msg to be delivered
|
||||
sleep(1);
|
||||
|
||||
$num_messages = imap_check($imap_stream)->Nmsgs;
|
||||
for ($i = $num_messages; $i > 0; $i--) {
|
||||
$info = imap_headerinfo($imap_stream, $i);
|
||||
if ($info->subject === $subject) {
|
||||
$header = imap_fetchheader($imap_stream, $i);
|
||||
echo "Return-Path header found: ";
|
||||
var_dump(strpos($header, 'Return-Path: joe@example.com') !== false);
|
||||
echo "To header found: ";
|
||||
var_dump(strpos($header, 'To: "<bob@example.com>" <info@mail.local>') !== false);
|
||||
echo "From header found: ";
|
||||
var_dump(strpos($header, 'From: "<bob@example.com>" <joe@example.com>') !== false);
|
||||
echo "Cc header found: ";
|
||||
var_dump(strpos($header, 'Cc: "Lastname, Firstname\\\\" <admin@mail.local>') !== false);
|
||||
imap_delete($imap_stream, $i);
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$repeat_count--;
|
||||
}
|
||||
|
||||
imap_close($imap_stream, CL_EXPUNGE);
|
||||
return $found;
|
||||
}
|
||||
|
||||
$to = "\"<bob@example.com>\" <{$users[1]}@$domain>";
|
||||
$subject = bin2hex(random_bytes(16));
|
||||
$message = 'hello';
|
||||
$headers = "From: \"<bob@example.com>\" <joe@example.com>\r\n"
|
||||
. "Cc: \"Lastname, Firstname\\\\\" <{$users[2]}@$domain>\r\n"
|
||||
. "Bcc: \"Firstname \\\"Ni,ck\\\" Lastname\" <{$users[3]}@$domain>\r\n";
|
||||
|
||||
$res = mail($to, $subject, $message, $headers);
|
||||
if ($res !== true) {
|
||||
die("TEST FAILED : Unable to send test email\n");
|
||||
} else {
|
||||
echo "Message sent OK\n";
|
||||
}
|
||||
|
||||
foreach ([$users[1], $users[2], $users[3]] as $user) {
|
||||
if (!find_and_delete_message("$user@$domain", $subject)) {
|
||||
echo "TEST FAILED: email not delivered\n";
|
||||
} else {
|
||||
echo "TEST PASSED: Message sent and deleted OK\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Message sent OK
|
||||
Return-Path header found: bool(true)
|
||||
To header found: bool(true)
|
||||
From header found: bool(true)
|
||||
Cc header found: bool(true)
|
||||
TEST PASSED: Message sent and deleted OK
|
||||
Return-Path header found: bool(true)
|
||||
To header found: bool(true)
|
||||
From header found: bool(true)
|
||||
Cc header found: bool(true)
|
||||
TEST PASSED: Message sent and deleted OK
|
||||
Return-Path header found: bool(true)
|
||||
To header found: bool(true)
|
||||
From header found: bool(true)
|
||||
Cc header found: bool(true)
|
||||
TEST PASSED: Message sent and deleted OK
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
Bug #75776 (Flushing streams with compression filter is broken)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('zlib')) die('skip zlib extension not available');
|
||||
if (!extension_loaded('bz2')) die('skip bz2 extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$compression = [
|
||||
'gz' => ['zlib.deflate', 'gzinflate'],
|
||||
'bz2' => ['bzip2.compress', 'bzdecompress']
|
||||
];
|
||||
foreach ($compression as $ext => [$filter, $function]) {
|
||||
$stream = fopen(__DIR__ . "/75776.$ext", 'w');
|
||||
stream_filter_append($stream, $filter);
|
||||
fwrite($stream,"sdfgdfg");
|
||||
fflush($stream);
|
||||
fclose($stream);
|
||||
|
||||
$compressed = file_get_contents(__DIR__ . "/75776.$ext");
|
||||
var_dump($function($compressed));
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
string(7) "sdfgdfg"
|
||||
string(7) "sdfgdfg"
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__ . "/75776.gz");
|
||||
@unlink(__DIR__ . "/75776.bz2");
|
||||
?>
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
/* edit configure.ac to change version number */
|
||||
#define PHP_MAJOR_VERSION 7
|
||||
#define PHP_MINOR_VERSION 4
|
||||
#define PHP_RELEASE_VERSION 16
|
||||
#define PHP_EXTRA_VERSION "-dev"
|
||||
#define PHP_VERSION "7.4.16-dev"
|
||||
#define PHP_VERSION_ID 70416
|
||||
#define PHP_RELEASE_VERSION 19
|
||||
#define PHP_EXTRA_VERSION ""
|
||||
#define PHP_VERSION "7.4.19"
|
||||
#define PHP_VERSION_ID 70419
|
||||
@@ -445,7 +445,7 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
|
||||
(close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0);
|
||||
#endif
|
||||
|
||||
if (stream->flags & PHP_STREAM_FLAG_WAS_WRITTEN) {
|
||||
if (stream->flags & PHP_STREAM_FLAG_WAS_WRITTEN || stream->writefilters.head) {
|
||||
/* make sure everything is saved */
|
||||
_php_stream_flush(stream, 1);
|
||||
}
|
||||
|
||||
+4
-1
@@ -797,7 +797,7 @@ HELP;
|
||||
|
||||
junit_save_xml();
|
||||
if (getenv('REPORT_EXIT_STATUS') !== '0' &&
|
||||
getenv('REPORT_EXIT_STATUS') !== 'no' && ($sum_results['FAILED'] || $sum_results['LEAKED'])) {
|
||||
getenv('REPORT_EXIT_STATUS') !== 'no' && ($sum_results['FAILED'] || $sum_results['BORKED'] || $sum_results['LEAKED'])) {
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
@@ -1273,6 +1273,9 @@ function system_with_timeout($commandline, $env = null, $stdin = null, $captureS
|
||||
}
|
||||
if ($stat["exitcode"] > 128 && $stat["exitcode"] < 160) {
|
||||
$data .= "\nTermsig=" . ($stat["exitcode"] - 128) . "\n";
|
||||
} else if (defined('PHP_WINDOWS_VERSION_MAJOR') && (($stat["exitcode"] >> 28) & 0b1111) === 0b1100) {
|
||||
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781
|
||||
$data .= "\nTermsig=" . $stat["exitcode"] . "\n";
|
||||
}
|
||||
|
||||
proc_close($proc);
|
||||
|
||||
+1
-1
@@ -642,7 +642,7 @@ static int do_cli(int argc, char **argv) /* {{{ */
|
||||
goto err;
|
||||
}
|
||||
request_started = 1;
|
||||
php_print_info(0xFFFFFFFF);
|
||||
php_print_info(PHP_INFO_ALL & ~PHP_INFO_CREDITS);
|
||||
php_output_end_all();
|
||||
exit_status = (c == '?' && argc > 1 && !strchr(argv[1], c));
|
||||
goto out;
|
||||
|
||||
+16
-12
@@ -39,6 +39,16 @@ static struct fpm_array_s sockets_list;
|
||||
|
||||
enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 };
|
||||
|
||||
static inline void fpm_sockets_get_env_name(char *envname, unsigned idx) /* {{{ */
|
||||
{
|
||||
if (!idx) {
|
||||
strcpy(envname, "FPM_SOCKETS");
|
||||
} else {
|
||||
sprintf(envname, "FPM_SOCKETS_%d", idx);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
|
||||
{
|
||||
unsigned i;
|
||||
@@ -82,13 +92,11 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
|
||||
|
||||
if (env_value) {
|
||||
for (i = 0; i < socket_set_count; i++) {
|
||||
if (!i) {
|
||||
strcpy(envname, "FPM_SOCKETS");
|
||||
} else {
|
||||
sprintf(envname, "FPM_SOCKETS_%d", i);
|
||||
}
|
||||
fpm_sockets_get_env_name(envname, i);
|
||||
setenv(envname, env_value + socket_set[i], 1);
|
||||
}
|
||||
fpm_sockets_get_env_name(envname, socket_set_count);
|
||||
unsetenv(envname);
|
||||
free(env_value);
|
||||
}
|
||||
|
||||
@@ -373,7 +381,7 @@ int fpm_sockets_init_main() /* {{{ */
|
||||
{
|
||||
unsigned i, lq_len;
|
||||
struct fpm_worker_pool_s *wp;
|
||||
char sockname[32];
|
||||
char envname[32];
|
||||
char sockpath[256];
|
||||
char *inherited;
|
||||
struct listening_socket_s *ls;
|
||||
@@ -384,12 +392,8 @@ int fpm_sockets_init_main() /* {{{ */
|
||||
|
||||
/* import inherited sockets */
|
||||
for (i = 0; i < FPM_ENV_SOCKET_SET_MAX; i++) {
|
||||
if (!i) {
|
||||
strcpy(sockname, "FPM_SOCKETS");
|
||||
} else {
|
||||
sprintf(sockname, "FPM_SOCKETS_%d", i);
|
||||
}
|
||||
inherited = getenv(sockname);
|
||||
fpm_sockets_get_env_name(envname, i);
|
||||
inherited = getenv(envname);
|
||||
if (!inherited) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ log_level = notice
|
||||
include = {{INCLUDE:CONF}}
|
||||
EOT;
|
||||
|
||||
$cfgPoolTemplate = <<<EOT
|
||||
$cfg['poolTemplate'] = <<<EOT
|
||||
[%name%]
|
||||
listen = {{ADDR[%name%]}}
|
||||
user = foo
|
||||
@@ -25,10 +25,7 @@ pm = ondemand
|
||||
pm.max_children = 5
|
||||
EOT;
|
||||
|
||||
$names = ['cccc', 'aaaa', 'eeee', 'dddd', 'bbbb'];
|
||||
foreach($names as $name) {
|
||||
$cfg[$name] = str_replace('%name%', $name, $cfgPoolTemplate);
|
||||
}
|
||||
$cfg['names'] = ['cccc', 'aaaa', 'eeee', 'dddd', 'bbbb'];
|
||||
|
||||
$tester = new FPM\Tester($cfg);
|
||||
$tester->start();
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
FPM: bug80024 - Duplication of info about inherited socket after pool removing
|
||||
--SKIPIF--
|
||||
<?php include "skipif.inc"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once "tester.inc";
|
||||
|
||||
$cfg['main'] = <<<EOT
|
||||
[global]
|
||||
error_log = {{FILE:LOG}}
|
||||
pid = {{FILE:PID}}
|
||||
include = {{INCLUDE:CONF}}
|
||||
EOT;
|
||||
|
||||
$cfg['poolTemplate'] = <<<EOT
|
||||
[pool_%index%]
|
||||
listen = {{ADDR:UDS[pool_%index%]}}
|
||||
pm = ondemand
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
pm.max_children = 5
|
||||
EOT;
|
||||
|
||||
$cfg['count'] = 129;
|
||||
|
||||
$tester = new FPM\Tester($cfg);
|
||||
$tester->start();
|
||||
$tester->expectLogStartNotices();
|
||||
$cfg['count'] = 128;
|
||||
$tester->reload($cfg);
|
||||
$tester->expectLogReloadingNotices(129);
|
||||
$tester->reload();
|
||||
$tester->expectLogReloadingNotices(128);
|
||||
$tester->terminate();
|
||||
$tester->expectLogTerminatingNotices();
|
||||
$tester->close();
|
||||
|
||||
?>
|
||||
Done
|
||||
--EXPECT--
|
||||
Done
|
||||
--CLEAN--
|
||||
<?php
|
||||
require_once "tester.inc";
|
||||
FPM\Tester::clean();
|
||||
?>
|
||||
@@ -9,6 +9,12 @@ class LogTool
|
||||
const P_PREFIX_STDOUT = '\[pool unconfined\] child \d+ said into stdout: ';
|
||||
const FINAL_SUFFIX = ', pipe is closed';
|
||||
|
||||
const DEBUG = 'DEBUG';
|
||||
const NOTICE = 'NOTICE';
|
||||
const WARNING = 'WARNING';
|
||||
const ERROR = 'ERROR';
|
||||
const ALERT = 'ALERT';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -278,6 +284,28 @@ class LogTool
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $lines
|
||||
* @return bool
|
||||
*/
|
||||
public function expectReloadingLines(array $lines)
|
||||
{
|
||||
if (
|
||||
!$this->expectNotice($lines[0], 'Reloading in progress ...') ||
|
||||
!$this->expectNotice($lines[1], 'reloading: .*')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 2; $i < count($lines) - 2; $i++) {
|
||||
if (!$this->expectNotice($lines[$i], 'using inherited socket fd=\d+, "[^"]+"')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->expectStartingLines(array_splice($lines, $i));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $lines
|
||||
* @return bool
|
||||
@@ -359,7 +387,7 @@ class LogTool
|
||||
*/
|
||||
public function expectDebug(string $line, string $expectedMessage, $pool = null)
|
||||
{
|
||||
return $this->expectEntry('DEBUG', $line, $expectedMessage, $pool);
|
||||
return $this->expectEntry(self::DEBUG, $line, $expectedMessage, $pool);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,7 +398,7 @@ class LogTool
|
||||
*/
|
||||
public function expectNotice(string $line, string $expectedMessage, $pool = null)
|
||||
{
|
||||
return $this->expectEntry('NOTICE', $line, $expectedMessage, $pool);
|
||||
return $this->expectEntry(self::NOTICE, $line, $expectedMessage, $pool);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,7 +409,7 @@ class LogTool
|
||||
*/
|
||||
public function expectWarning(string $line, string $expectedMessage, $pool = null)
|
||||
{
|
||||
return $this->expectEntry('WARNING', $line, $expectedMessage, $pool);
|
||||
return $this->expectEntry(self::WARNING, $line, $expectedMessage, $pool);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,7 +420,7 @@ class LogTool
|
||||
*/
|
||||
public function expectError(string $line, string $expectedMessage, $pool = null)
|
||||
{
|
||||
return $this->expectEntry('ERROR', $line, $expectedMessage, $pool);
|
||||
return $this->expectEntry(self::ERROR, $line, $expectedMessage, $pool);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,10 +431,9 @@ class LogTool
|
||||
*/
|
||||
public function expectAlert(string $line, string $expectedMessage, $pool = null)
|
||||
{
|
||||
return $this->expectEntry('ALERT', $line, $expectedMessage, $pool);
|
||||
return $this->expectEntry(self::ALERT, $line, $expectedMessage, $pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $msg
|
||||
* @return bool
|
||||
|
||||
+109
-15
@@ -72,7 +72,7 @@ class Tester
|
||||
/**
|
||||
* Configuration template
|
||||
*
|
||||
* @var string
|
||||
* @var string|array
|
||||
*/
|
||||
private $configTemplate;
|
||||
|
||||
@@ -152,7 +152,14 @@ class Tester
|
||||
unlink($filePath);
|
||||
}
|
||||
}
|
||||
// clean config files
|
||||
|
||||
self::cleanConfigFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean config files
|
||||
*/
|
||||
static public function cleanConfigFiles() {
|
||||
if (is_dir(self::CONF_DIR)) {
|
||||
foreach(glob(self::CONF_DIR . '/*.conf') as $name) {
|
||||
unlink($name);
|
||||
@@ -686,6 +693,12 @@ class Tester
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->debug) {
|
||||
foreach ($lines as $line) {
|
||||
echo "LOG LINE: " . $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
@@ -731,6 +744,24 @@ class Tester
|
||||
return getmygid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload FPM by sending USR2 signal and optionally change config before that.
|
||||
*
|
||||
* @param string|array $configTemplate
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function reload($configTemplate = null)
|
||||
{
|
||||
if (!is_null($configTemplate)) {
|
||||
self::cleanConfigFiles();
|
||||
$this->configTemplate = $configTemplate;
|
||||
$this->createConfig();
|
||||
}
|
||||
|
||||
return $this->signal('USR2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send signal to the supplied PID or the server PID.
|
||||
*
|
||||
@@ -784,14 +815,13 @@ class Tester
|
||||
throw new \Exception('The config template array has to have main config');
|
||||
}
|
||||
$mainTemplate = $configTemplates['main'];
|
||||
unset($configTemplates['main']);
|
||||
if (!is_dir(self::CONF_DIR)) {
|
||||
mkdir(self::CONF_DIR);
|
||||
}
|
||||
foreach ($configTemplates as $name => $configTemplate) {
|
||||
foreach ($this->createPoolConfigs($configTemplates) as $name => $poolConfig) {
|
||||
$this->makeFile(
|
||||
'conf',
|
||||
$this->processTemplate($configTemplate),
|
||||
$this->processTemplate($poolConfig),
|
||||
self::CONF_DIR,
|
||||
$name
|
||||
);
|
||||
@@ -803,6 +833,36 @@ class Tester
|
||||
return $this->makeFile($extension, $this->processTemplate($mainTemplate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create pool config templates.
|
||||
*
|
||||
* @param array $configTemplates
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function createPoolConfigs(array $configTemplates)
|
||||
{
|
||||
if (!isset($configTemplates['poolTemplate'])) {
|
||||
unset($configTemplates['main']);
|
||||
return $configTemplates;
|
||||
}
|
||||
$poolTemplate = $configTemplates['poolTemplate'];
|
||||
$configs = [];
|
||||
if (isset($configTemplates['count'])) {
|
||||
$start = $configTemplates['start'] ?? 1;
|
||||
for ($i = $start; $i < $start + $configTemplates['count']; $i++) {
|
||||
$configs[$i] = str_replace('%index%', $i, $poolTemplate);
|
||||
}
|
||||
} elseif (isset($configTemplates['names'])) {
|
||||
foreach($configTemplates['names'] as $name) {
|
||||
$configs[$name] = str_replace('%name%', $name, $poolTemplate);
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('The config template requires count or names if poolTemplate set');
|
||||
}
|
||||
return $configs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process template string.
|
||||
*
|
||||
@@ -1110,6 +1170,16 @@ class Tester
|
||||
$this->logTool->checkTruncatedMessage($this->response->getErrorData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect reloading lines to be logged.
|
||||
*
|
||||
* @param int $socketCount
|
||||
*/
|
||||
public function expectLogReloadingNotices($socketCount = 1)
|
||||
{
|
||||
$this->logTool->expectReloadingLines($this->getLogLines($socketCount + 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect starting lines to be logged.
|
||||
*/
|
||||
@@ -1176,16 +1246,36 @@ class Tester
|
||||
return $this->logTool->checkWrappedMessage($logLines, false, true, $is_stderr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect log entry.
|
||||
*
|
||||
* @param string $type The log type
|
||||
* @param string $message The expected message
|
||||
* @param string|null $pool The pool for pool prefixed log entry
|
||||
* @param int $count The number of items
|
||||
* @return bool
|
||||
*/
|
||||
private function expectLogEntry(string $type, string $message, $pool = null, $count = 1)
|
||||
{
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (!$this->logTool->expectEntry($type, $this->getLastLogLine(), $message, $pool)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect a log debug message.
|
||||
*
|
||||
* @param string $message
|
||||
* @param string|null $pool
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function expectLogDebug(string $message, $pool = null)
|
||||
public function expectLogDebug(string $message, $pool = null, $count = 1)
|
||||
{
|
||||
return $this->logTool->expectDebug($this->getLastLogLine(), $message, $pool);
|
||||
return $this->expectLogEntry(LogTool::DEBUG, $message, $pool, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1193,11 +1283,12 @@ class Tester
|
||||
*
|
||||
* @param string $message
|
||||
* @param string|null $pool
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function expectLogNotice(string $message, $pool = null)
|
||||
public function expectLogNotice(string $message, $pool = null, $count = 1)
|
||||
{
|
||||
return $this->logTool->expectNotice($this->getLastLogLine(), $message, $pool);
|
||||
return $this->expectLogEntry(LogTool::NOTICE, $message, $pool, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1205,11 +1296,12 @@ class Tester
|
||||
*
|
||||
* @param string $message
|
||||
* @param string|null $pool
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function expectLogWarning(string $message, $pool = null)
|
||||
public function expectLogWarning(string $message, $pool = null, $count = 1)
|
||||
{
|
||||
return $this->logTool->expectWarning($this->getLastLogLine(), $message, $pool);
|
||||
return $this->expectLogEntry(LogTool::WARNING, $message, $pool, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1217,11 +1309,12 @@ class Tester
|
||||
*
|
||||
* @param string $message
|
||||
* @param string|null $pool
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function expectLogError(string $message, $pool = null)
|
||||
public function expectLogError(string $message, $pool = null, $count = 1)
|
||||
{
|
||||
return $this->logTool->expectError($this->getLastLogLine(), $message, $pool);
|
||||
return $this->expectLogEntry(LogTool::ERROR, $message, $pool, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1229,11 +1322,12 @@ class Tester
|
||||
*
|
||||
* @param string $message
|
||||
* @param string|null $pool
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function expectLogAlert(string $message, $pool = null)
|
||||
public function expectLogAlert(string $message, $pool = null, $count = 1)
|
||||
{
|
||||
return $this->logTool->expectAlert($this->getLastLogLine(), $message, $pool);
|
||||
return $this->expectLogEntry(LogTool::ALERT, $message, $pool, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -603,7 +603,7 @@ static int sapi_lsapi_activate()
|
||||
static sapi_module_struct lsapi_sapi_module =
|
||||
{
|
||||
"litespeed",
|
||||
"LiteSpeed V7.7",
|
||||
"LiteSpeed V7.9",
|
||||
|
||||
php_lsapi_startup, /* startup */
|
||||
php_module_shutdown_wrapper, /* shutdown */
|
||||
@@ -806,7 +806,7 @@ static int alter_ini( const char * pKey, int keyLen, const char * pValue, int va
|
||||
Use ACTIVATE stage in legacy mode only.
|
||||
|
||||
RUNTIME stage should be used here,
|
||||
as with ACTIVATE it's impossible to change the option from script with ini_set
|
||||
as with ACTIVATE it's impossible to change the option from script with ini_set
|
||||
*/
|
||||
if(!mod_lsapi_mode)
|
||||
{
|
||||
|
||||
+53
-36
@@ -152,7 +152,7 @@ static int s_ppid;
|
||||
static int s_restored_ppid = 0;
|
||||
static int s_pid = 0;
|
||||
static int s_slow_req_msecs = 0;
|
||||
static int s_keepListener = 0;
|
||||
static int s_keep_listener = 1;
|
||||
static int s_dump_debug_info = 0;
|
||||
static int s_pid_dump_debug_info = 0;
|
||||
static int s_req_processed = 0;
|
||||
@@ -244,8 +244,8 @@ void LSAPI_Log(int flag, const char * fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
char *p = buf;
|
||||
if ((flag & LSAPI_LOG_TIMESTAMP_BITS) &&
|
||||
!((flag & LSAPI_LOG_TIMESTAMP_STDERR) && s_stderr_is_pipe))
|
||||
if ((flag & LSAPI_LOG_TIMESTAMP_BITS)
|
||||
&& !(s_stderr_is_pipe))
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm tm;
|
||||
@@ -272,7 +272,7 @@ void LSAPI_Log(int flag, const char * fmt, ...)
|
||||
|
||||
if (flag & LSAPI_LOG_PID)
|
||||
{
|
||||
p += snprintf(p, 100, "[%d] ", s_pid);
|
||||
p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid);
|
||||
}
|
||||
|
||||
if (p > buf)
|
||||
@@ -294,7 +294,13 @@ void LSAPI_Log(int flag, const char * fmt, ...)
|
||||
|
||||
#endif
|
||||
|
||||
#define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_TIMESTAMP_STDERR|LSAPI_LOG_PID, __VA_ARGS__)
|
||||
#define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__)
|
||||
|
||||
|
||||
void lsapi_perror(const char * pMessage, int err_no)
|
||||
{
|
||||
lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no));
|
||||
}
|
||||
|
||||
|
||||
static int lsapi_parent_dead()
|
||||
@@ -893,7 +899,8 @@ int LSAPI_is_suEXEC_Daemon(void)
|
||||
static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
|
||||
{
|
||||
char achError[4096];
|
||||
int n = snprintf(achError, sizeof(achError), "[%d] %s:%s: %s\n", getpid(),
|
||||
int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n",
|
||||
getuid(), getpid(),
|
||||
pErr1, (pErr2)?pErr2:"", strerror(errno));
|
||||
if (n > (int)sizeof(achError))
|
||||
n = sizeof(achError);
|
||||
@@ -939,7 +946,7 @@ static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
|
||||
ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
|
||||
if ( ret < 0 )
|
||||
{
|
||||
lsapi_log("enter LVE (%d) : ressult: %d !\n", uid, ret );
|
||||
//lsapi_log("enter LVE (%d) : ressult: %d !\n", uid, ret );
|
||||
LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
|
||||
lsapi_lve_error( pReq );
|
||||
return -1;
|
||||
@@ -2938,6 +2945,7 @@ static void lsapi_sigchild( int signal )
|
||||
|
||||
static int lsapi_init_children_status(void)
|
||||
{
|
||||
char * pBuf;
|
||||
int size = 4096;
|
||||
int max_children;
|
||||
if (g_prefork_server->m_pChildrenStatus)
|
||||
@@ -2945,7 +2953,6 @@ static int lsapi_init_children_status(void)
|
||||
max_children = g_prefork_server->m_iMaxChildren
|
||||
+ g_prefork_server->m_iExtraChildren;
|
||||
|
||||
char * pBuf;
|
||||
size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
|
||||
size = (size + 4095) / 4096 * 4096;
|
||||
pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
|
||||
@@ -2978,9 +2985,9 @@ static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
|
||||
return;
|
||||
}
|
||||
|
||||
lsapi_log("Possible runaway process, PPID: %d, PID: %d, "
|
||||
lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, "
|
||||
"reqCount: %d, process time: %ld, checkpoint time: %ld, start "
|
||||
"time: %ld\n", getpid(), pStatus->m_pid,
|
||||
"time: %ld\n", getuid(), getppid(), pStatus->m_pid,
|
||||
pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
|
||||
tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
|
||||
|
||||
@@ -3008,12 +3015,11 @@ static void lsapi_check_child_status( long tmCur )
|
||||
while( pStatus < pEnd )
|
||||
{
|
||||
tobekilled = 0;
|
||||
if ( pStatus->m_pid != 0 )
|
||||
if ( pStatus->m_pid != 0 && pStatus->m_pid != -1)
|
||||
{
|
||||
++count;
|
||||
if ( !pStatus->m_inProcess )
|
||||
{
|
||||
|
||||
if (g_prefork_server->m_iCurChildren - dying
|
||||
> g_prefork_server->m_iMaxChildren
|
||||
|| idle > g_prefork_server->m_iMaxIdleChildren)
|
||||
@@ -3030,7 +3036,7 @@ static void lsapi_check_child_status( long tmCur )
|
||||
//tobekilled = SIGUSR1;
|
||||
}
|
||||
}
|
||||
if ( !tobekilled )
|
||||
if (!pStatus->m_iKillSent)
|
||||
++idle;
|
||||
}
|
||||
else
|
||||
@@ -3184,6 +3190,9 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||
|
||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
|
||||
*s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
|
||||
// lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
|
||||
// s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
|
||||
|
||||
#endif
|
||||
FD_ZERO( &readfds );
|
||||
FD_SET( pServer->m_fd, &readfds );
|
||||
@@ -3196,7 +3205,8 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||
if (s_accepting_workers)
|
||||
accepting = __sync_add_and_fetch(s_accepting_workers, 0);
|
||||
|
||||
if (pServer->m_iCurChildren > 0 && accepting > 0)
|
||||
if (pServer->m_iCurChildren > 0
|
||||
&& accepting > 0)
|
||||
{
|
||||
usleep(400);
|
||||
while(accepting-- > 0)
|
||||
@@ -3265,10 +3275,10 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||
__sync_add_and_fetch(s_busy_workers, 1);
|
||||
lsapi_set_nblock( pReq->m_fd, 0 );
|
||||
//keep it open if busy_count is used.
|
||||
if (s_busy_workers
|
||||
if (!s_keep_listener && s_busy_workers
|
||||
&& *s_busy_workers > (pServer->m_iMaxChildren >> 1))
|
||||
s_keepListener = 1;
|
||||
if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
|
||||
s_keep_listener = 1;
|
||||
if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
|
||||
&& pReq->m_fdListen != -1 )
|
||||
{
|
||||
close( pReq->m_fdListen );
|
||||
@@ -3289,7 +3299,9 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||
}
|
||||
else if ( pid == -1 )
|
||||
{
|
||||
perror( "fork() failed, please increase process limit" );
|
||||
lsapi_perror("fork() failed, please increase process limit", errno);
|
||||
if (child_status)
|
||||
child_status->m_pid = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3312,7 +3324,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||
{
|
||||
if (( errno == EINTR )||( errno == EAGAIN))
|
||||
continue;
|
||||
perror( "accept() failed" );
|
||||
lsapi_perror("accept() failed", errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -3350,10 +3362,10 @@ int LSAPI_Postfork_Child(LSAPI_Request * pReq)
|
||||
__sync_add_and_fetch(s_busy_workers, 1);
|
||||
lsapi_set_nblock( pReq->m_fd, 0 );
|
||||
//keep it open if busy_count is used.
|
||||
if (s_busy_workers
|
||||
if (!s_keep_listener && s_busy_workers
|
||||
&& *s_busy_workers > (max_children >> 1))
|
||||
s_keepListener = 1;
|
||||
if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
|
||||
s_keep_listener = 1;
|
||||
if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
|
||||
&& pReq->m_fdListen != -1 )
|
||||
{
|
||||
close(pReq->m_fdListen);
|
||||
@@ -3512,7 +3524,7 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
|
||||
{
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
perror( "accept() failed" );
|
||||
lsapi_perror("accept() failed", errno);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
@@ -3528,13 +3540,6 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
|
||||
}
|
||||
|
||||
|
||||
void lsapi_perror( const char * pMessage, int err_no )
|
||||
{
|
||||
lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no,
|
||||
strerror( err_no ) );
|
||||
}
|
||||
|
||||
|
||||
int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
|
||||
{
|
||||
int fd;
|
||||
@@ -3620,9 +3625,21 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
|
||||
if ( s_worker_status )
|
||||
{
|
||||
s_worker_status->m_inProcess = 0;
|
||||
if (fd == pReq->m_fdListen
|
||||
&& (s_keepListener != 2 || !is_enough_free_mem()))
|
||||
return -1;
|
||||
if (fd == pReq->m_fdListen)
|
||||
{
|
||||
if (s_keep_listener == 0 || !is_enough_free_mem())
|
||||
return -1;
|
||||
if (s_keep_listener == 1)
|
||||
{
|
||||
int wait_time = 10;
|
||||
if (s_busy_workers)
|
||||
wait_time += *s_busy_workers * 10;
|
||||
if (s_accepting_workers)
|
||||
wait_time >>= (*s_accepting_workers);
|
||||
if (wait_secs >= wait_time)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
++wait_secs;
|
||||
if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
|
||||
@@ -3657,7 +3674,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
|
||||
|
||||
lsapi_set_nblock( fd, 0 );
|
||||
//init_conn_key( pReq->m_fd );
|
||||
if (!s_keepListener)
|
||||
if (!s_keep_listener)
|
||||
{
|
||||
close( pReq->m_fdListen );
|
||||
pReq->m_fdListen = -1;
|
||||
@@ -3949,7 +3966,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
|
||||
if ( p )
|
||||
{
|
||||
n = atoi( p );
|
||||
s_keepListener = n;
|
||||
s_keep_listener = n;
|
||||
}
|
||||
|
||||
p = getenv( "LSAPI_AVOID_FORK" );
|
||||
@@ -3958,7 +3975,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
|
||||
avoidFork = atoi( p );
|
||||
if (avoidFork)
|
||||
{
|
||||
s_keepListener = 2;
|
||||
s_keep_listener = 2;
|
||||
ch = *(p + strlen(p) - 1);
|
||||
if ( ch == 'G' || ch == 'g' )
|
||||
avoidFork *= 1024 * 1024 * 1024;
|
||||
|
||||
@@ -773,6 +773,7 @@ PHPDBG_COMMAND(run) /* {{{ */
|
||||
if (!PHPDBG_G(ops)) {
|
||||
if (phpdbg_compile() == FAILURE) {
|
||||
phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s, cannot run", PHPDBG_G(exec));
|
||||
EG(exit_status) = FAILURE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
+86
-16
@@ -333,6 +333,37 @@ PHPAPI char *GetSMErrorText(int index)
|
||||
}
|
||||
}
|
||||
|
||||
/* strtok_r like, but recognizes quoted-strings */
|
||||
static char *find_address(char *list, char **state)
|
||||
{
|
||||
zend_bool in_quotes = 0;
|
||||
char *p = list;
|
||||
|
||||
if (list == NULL) {
|
||||
if (*state == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p = list = *state;
|
||||
}
|
||||
*state = NULL;
|
||||
while ((p = strpbrk(p, ",\"\\")) != NULL) {
|
||||
if (*p == '\\' && in_quotes) {
|
||||
if (p[1] == '\0') {
|
||||
/* invalid address; let SMTP server deal with it */
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
} else if (*p == '"') {
|
||||
in_quotes = !in_quotes;
|
||||
} else if (*p == ',' && !in_quotes) {
|
||||
*p = '\0';
|
||||
*state = p + 1;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
// Name: SendText
|
||||
@@ -357,7 +388,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
{
|
||||
int res;
|
||||
char *p;
|
||||
char *tempMailTo, *token, *pos1, *pos2;
|
||||
char *tempMailTo, *token, *token_state, *pos1, *pos2;
|
||||
char *server_response = NULL;
|
||||
char *stripped_header = NULL;
|
||||
zend_string *data_cln;
|
||||
@@ -410,7 +441,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
|
||||
tempMailTo = estrdup(mailTo);
|
||||
/* Send mail to all rcpt's */
|
||||
token = strtok(tempMailTo, ",");
|
||||
token = find_address(tempMailTo, &token_state);
|
||||
while (token != NULL)
|
||||
{
|
||||
SMTP_SKIP_SPACE(token);
|
||||
@@ -424,14 +455,14 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
efree(tempMailTo);
|
||||
return (res);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
token = find_address(NULL, &token_state);
|
||||
}
|
||||
efree(tempMailTo);
|
||||
|
||||
if (mailCc && *mailCc) {
|
||||
tempMailTo = estrdup(mailCc);
|
||||
/* Send mail to all rcpt's */
|
||||
token = strtok(tempMailTo, ",");
|
||||
token = find_address(tempMailTo, &token_state);
|
||||
while (token != NULL)
|
||||
{
|
||||
SMTP_SKIP_SPACE(token);
|
||||
@@ -445,7 +476,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
efree(tempMailTo);
|
||||
return (res);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
token = find_address(NULL, &token_state);
|
||||
}
|
||||
efree(tempMailTo);
|
||||
}
|
||||
@@ -471,7 +502,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
tempMailTo = estrndup(pos1, pos2 - pos1);
|
||||
}
|
||||
|
||||
token = strtok(tempMailTo, ",");
|
||||
token = find_address(tempMailTo, &token_state);
|
||||
while (token != NULL)
|
||||
{
|
||||
SMTP_SKIP_SPACE(token);
|
||||
@@ -485,7 +516,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
efree(tempMailTo);
|
||||
return (res);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
token = find_address(NULL,&token_state);
|
||||
}
|
||||
efree(tempMailTo);
|
||||
}
|
||||
@@ -496,7 +527,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
if (mailBcc && *mailBcc) {
|
||||
tempMailTo = estrdup(mailBcc);
|
||||
/* Send mail to all rcpt's */
|
||||
token = strtok(tempMailTo, ",");
|
||||
token = find_address(tempMailTo, &token_state);
|
||||
while (token != NULL)
|
||||
{
|
||||
SMTP_SKIP_SPACE(token);
|
||||
@@ -510,7 +541,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
efree(tempMailTo);
|
||||
return (res);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
token = find_address(NULL, &token_state);
|
||||
}
|
||||
efree(tempMailTo);
|
||||
}
|
||||
@@ -544,7 +575,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
}
|
||||
}
|
||||
|
||||
token = strtok(tempMailTo, ",");
|
||||
token = find_address(tempMailTo, &token_state);
|
||||
while (token != NULL)
|
||||
{
|
||||
SMTP_SKIP_SPACE(token);
|
||||
@@ -558,7 +589,7 @@ static int SendText(char *RPath, char *Subject, char *mailTo, char *mailCc, char
|
||||
efree(tempMailTo);
|
||||
return (res);
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
token = find_address(NULL, &token_state);
|
||||
}
|
||||
efree(tempMailTo);
|
||||
|
||||
@@ -978,6 +1009,46 @@ static unsigned long GetAddr(LPSTR szHost)
|
||||
return (lAddr);
|
||||
} /* end GetAddr() */
|
||||
|
||||
/* returns the contents of an angle-addr (caller needs to efree) or NULL */
|
||||
static char *get_angle_addr(char *address)
|
||||
{
|
||||
zend_bool in_quotes = 0;
|
||||
char *p1 = address, *p2;
|
||||
|
||||
while ((p1 = strpbrk(p1, "<\"\\")) != NULL) {
|
||||
if (*p1 == '\\' && in_quotes) {
|
||||
if (p1[1] == '\0') {
|
||||
/* invalid address; let SMTP server deal with it */
|
||||
return NULL;
|
||||
}
|
||||
p1++;
|
||||
} else if (*p1 == '"') {
|
||||
in_quotes = !in_quotes;
|
||||
} else if (*p1 == '<' && !in_quotes) {
|
||||
break;
|
||||
}
|
||||
p1++;
|
||||
}
|
||||
if (p1 == NULL) return NULL;
|
||||
p2 = ++p1;
|
||||
while ((p2 = strpbrk(p2, ">\"\\")) != NULL) {
|
||||
if (*p2 == '\\' && in_quotes) {
|
||||
if (p2[1] == '\0') {
|
||||
/* invalid address; let SMTP server deal with it */
|
||||
return NULL;
|
||||
}
|
||||
p2++;
|
||||
} else if (*p2 == '"') {
|
||||
in_quotes = !in_quotes;
|
||||
} else if (*p2 == '>' && !in_quotes) {
|
||||
break;
|
||||
}
|
||||
p2++;
|
||||
}
|
||||
if (p2 == NULL) return NULL;
|
||||
|
||||
return estrndup(p1, p2 - p1);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
// Name: int FormatEmailAddress
|
||||
@@ -993,13 +1064,12 @@ static unsigned long GetAddr(LPSTR szHost)
|
||||
// History:
|
||||
//********************************************************************/
|
||||
static int FormatEmailAddress(char* Buf, char* EmailAddress, char* FormatString) {
|
||||
char *tmpAddress1, *tmpAddress2;
|
||||
char *tmpAddress;
|
||||
int result;
|
||||
|
||||
if( (tmpAddress1 = strchr(EmailAddress, '<')) && (tmpAddress2 = strchr(tmpAddress1, '>')) ) {
|
||||
*tmpAddress2 = 0; // terminate the string temporarily.
|
||||
result = snprintf(Buf, MAIL_BUFFER_SIZE, FormatString , tmpAddress1+1);
|
||||
*tmpAddress2 = '>'; // put it back the way it was.
|
||||
if ((tmpAddress = get_angle_addr(EmailAddress)) != NULL) {
|
||||
result = snprintf(Buf, MAIL_BUFFER_SIZE, FormatString, tmpAddress);
|
||||
efree(tmpAddress);
|
||||
return result;
|
||||
}
|
||||
return snprintf(Buf, MAIL_BUFFER_SIZE , FormatString , EmailAddress );
|
||||
|
||||
Reference in new issue
Block a user