mirror of
https://github.com/bdnugget/php-src.git
synced 2026-11-10 18:50:50 +00:00
Compare commits
29
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41c207aed2 | ||
|
|
9544aac446 | ||
|
|
03596d7648 | ||
|
|
3c10649464 | ||
|
|
e8a89c49db | ||
|
|
5d31ee302d | ||
|
|
68f5289e9e | ||
|
|
38ad37ad43 | ||
|
|
25103c37aa | ||
|
|
9450893dc6 | ||
|
|
d1b1c04398 | ||
|
|
5c963731e2 | ||
|
|
6b631f073d | ||
|
|
46d6daea7a | ||
|
|
e65932060a | ||
|
|
ec589a27da | ||
|
|
65d7ade684 | ||
|
|
2498385dd9 | ||
|
|
8967e66559 | ||
|
|
434c2b1bdb | ||
|
|
128fca4037 | ||
|
|
2d3d72412a | ||
|
|
0db6f5267c | ||
|
|
70dfbe0068 | ||
|
|
b043759cb4 | ||
|
|
bc166844e3 | ||
|
|
315f3f8dc9 | ||
|
|
118ff03335 | ||
|
|
078cdd8f76 |
No files matched your search
@@ -352,7 +352,8 @@ define ____print_ht
|
||||
end
|
||||
printf "[%d] ", $i
|
||||
if $p->key
|
||||
printf "%s => ", $p->key->val
|
||||
____print_str $p->key->val $p->key->len
|
||||
printf " => "
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
|
||||
@@ -70,10 +70,13 @@ jobs:
|
||||
include:
|
||||
- env: ENABLE_MAINTAINER_ZTS=0 ENABLE_DEBUG=0
|
||||
arch: amd64
|
||||
if: type = cron
|
||||
- env: ENABLE_MAINTAINER_ZTS=1 ENABLE_DEBUG=1
|
||||
arch: amd64
|
||||
if: type = cron
|
||||
- env: ENABLE_MAINTAINER_ZTS=1 ENABLE_DEBUG=1 SKIP_IO_CAPTURE_TESTS=1 ARM64=1
|
||||
arch: arm64
|
||||
if: type = cron
|
||||
|
||||
before_script:
|
||||
- ccache --version
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
21 Jan 2021, PHP 7.4.15RC2
|
||||
|
||||
- Core:
|
||||
. Fixed bug #80523 (bogus parse error on >4GB source code). (Nikita)
|
||||
. Fixed bug #80384 (filter buffers entire read until file closed). (Adam
|
||||
Seitz, cmb)
|
||||
|
||||
- Curl:
|
||||
. Fixed bug #80595 (Resetting POSTFIELDS to empty array breaks request). (cmb)
|
||||
|
||||
- Date:
|
||||
. Fixed bug #80376 (last day of the month causes runway cpu usage. (Derick)
|
||||
|
||||
- MySQLi:
|
||||
. Fixed bug #67983 (mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to
|
||||
interpret bit columns). (Nikita)
|
||||
. Fixed bug #64638 (Fetching resultsets from stored procedure with cursor
|
||||
fails). (Nikita)
|
||||
. Fixed bug #72862 (segfault using prepared statements on stored procedures
|
||||
that use a cursor). (Nikita)
|
||||
. Fixed bug #77935 (Crash in mysqlnd_fetch_stmt_row_cursor when calling an SP
|
||||
with a cursor). (Nikita)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug #77565 (Incorrect locator detection in ZIP-based phars). (cmb)
|
||||
. Fixed bug #69279 (Compressed ZIP Phar extractTo() creates garbage files).
|
||||
(cmb)
|
||||
|
||||
07 Jan 2021, PHP 7.4.14
|
||||
|
||||
- Core:
|
||||
@@ -50,7 +78,7 @@ PHP NEWS
|
||||
PROCEDURE resultset SIGNAL). (Nikita)
|
||||
|
||||
- Standard:
|
||||
. Fixed bug #77423 (FILTER_VALIDATE_URL accepts URLs with invalid userinfo).
|
||||
. Fixed bug #77423 (FILTER_VALIDATE_URL accepts URLs with invalid userinfo).
|
||||
(CVE-2020-7071) (cmb)
|
||||
. Fixed bug #80366 (Return Value of zend_fstat() not Checked). (sagpant, cmb)
|
||||
. Fixed bug #80411 (References to null-serialized object break serialize()).
|
||||
|
||||
@@ -177,7 +177,7 @@ static void yy_pop_state(void)
|
||||
zend_stack_del_top(&SCNG(state_stack));
|
||||
}
|
||||
|
||||
static void yy_scan_buffer(char *str, unsigned int len)
|
||||
static void yy_scan_buffer(char *str, size_t len)
|
||||
{
|
||||
YYCURSOR = (YYCTYPE*)str;
|
||||
YYLIMIT = YYCURSOR + len;
|
||||
@@ -554,7 +554,7 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle)
|
||||
}
|
||||
}
|
||||
SCNG(yy_start) = (unsigned char *)buf;
|
||||
yy_scan_buffer(buf, (unsigned int)size);
|
||||
yy_scan_buffer(buf, size);
|
||||
} else {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
|
||||
}
|
||||
@@ -722,7 +722,7 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
yy_scan_buffer(buf, (unsigned int)size);
|
||||
yy_scan_buffer(buf, size);
|
||||
|
||||
new_compiled_filename = zend_string_init(filename, strlen(filename), 0);
|
||||
zend_set_compiled_filename(new_compiled_filename);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice.
|
||||
dnl ----------------------------------------------------------------------------
|
||||
|
||||
AC_PREREQ([2.68])
|
||||
AC_INIT([PHP],[7.4.14],[https://bugs.php.net],[php],[https://www.php.net])
|
||||
AC_INIT([PHP],[7.4.15RC2],[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
|
||||
|
||||
@@ -2969,7 +2969,14 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{
|
||||
|
||||
case CURLOPT_POSTFIELDS:
|
||||
if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) {
|
||||
return build_mime_structure_from_hash(ch, zvalue);
|
||||
if (zend_hash_num_elements(HASH_OF(zvalue)) == 0) {
|
||||
/* no need to build the mime structure for empty hashtables;
|
||||
also works around https://github.com/curl/curl/issues/6455 */
|
||||
curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, "");
|
||||
error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0);
|
||||
} else {
|
||||
return build_mime_structure_from_hash(ch, zvalue);
|
||||
}
|
||||
} else {
|
||||
#if LIBCURL_VERSION_NUM >= 0x071101
|
||||
zend_string *tmp_str;
|
||||
|
||||
@@ -21,9 +21,10 @@ var_dump(curl_getinfo($ch)["request_header"]);
|
||||
string(%d) "array(0) {
|
||||
}
|
||||
"
|
||||
string(90) "POST /get.inc?test=post HTTP/1.1
|
||||
string(%d) "POST /get.inc?test=post HTTP/1.1
|
||||
Host: localhost:%d
|
||||
Accept: */*
|
||||
Content-Length: 0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
"
|
||||
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Bug #80595 (Resetting POSTFIELDS to empty array breaks request)
|
||||
--SKIPIF--
|
||||
<?php include 'skipif.inc'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
include 'server.inc';
|
||||
$host = curl_cli_server_start();
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_URL => "{$host}/get.inc?test=post",
|
||||
]);
|
||||
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, ['foo' => 'bar']);
|
||||
var_dump(curl_exec($ch));
|
||||
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, []);
|
||||
var_dump(curl_exec($ch));
|
||||
?>
|
||||
--EXPECT--
|
||||
string(43) "array(1) {
|
||||
["foo"]=>
|
||||
string(3) "bar"
|
||||
}
|
||||
"
|
||||
string(13) "array(0) {
|
||||
}
|
||||
"
|
||||
+22837
-20045
File diff suppressed because it is too large.
Load diff
+395
-432
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
Bug #67983: mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to interpret bit columns
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once('skipif.inc');
|
||||
require_once('skipifconnectfailure.inc');
|
||||
if (!$IS_MYSQLND) {
|
||||
die("skip mysqlnd only test");
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once("connect.inc");
|
||||
|
||||
$connection = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
|
||||
|
||||
mysqli_options($connection, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
|
||||
|
||||
mysqli_set_charset($connection, 'utf8');
|
||||
mysqli_query($connection, 'DROP TABLE IF EXISTS test');
|
||||
mysqli_query($connection, 'CREATE TABLE test (id BIT(8))');
|
||||
mysqli_query($connection, 'INSERT INTO test VALUES (0), (1), (42)');
|
||||
|
||||
$res = mysqli_query($connection, 'SELECT * FROM test');
|
||||
|
||||
while ($result = mysqli_fetch_assoc($res)) {
|
||||
var_dump($result['id']);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(0)
|
||||
int(1)
|
||||
int(42)
|
||||
@@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
Bug #77935: Crash in mysqlnd_fetch_stmt_row_cursor when calling an SP with a cursor
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once('skipif.inc');
|
||||
require_once('skipifconnectfailure.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once(__DIR__ . '/connect.inc');
|
||||
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
$db = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
|
||||
$db->query('DROP PROCEDURE IF EXISTS testSp');
|
||||
$db->query(<<<'SQL'
|
||||
CREATE
|
||||
PROCEDURE `testSp`()
|
||||
BEGIN
|
||||
DECLARE `cur` CURSOR FOR SELECT 1;
|
||||
OPEN `cur`;
|
||||
CLOSE `cur`;
|
||||
SELECT 1;
|
||||
END;
|
||||
SQL);
|
||||
|
||||
$stmt = $db->prepare("CALL testSp()");
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
var_dump($row);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) {
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
@@ -110,21 +110,7 @@ if (!function_exists('mysqli_stmt_get_result'))
|
||||
|
||||
mysqli_stmt_close($stmt);
|
||||
|
||||
if (!$stmt = mysqli_stmt_init($link))
|
||||
printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
|
||||
if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
|
||||
printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
if (!mysqli_stmt_execute($stmt))
|
||||
printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
$id = NULL;
|
||||
$label = NULL;
|
||||
if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
|
||||
printf("[035] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
|
||||
|
||||
// get_result cannot be used in PS cursor mode
|
||||
// get_result can be used in PS cursor mode
|
||||
if (!$stmt = mysqli_stmt_init($link))
|
||||
printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
|
||||
@@ -137,24 +123,11 @@ if (!function_exists('mysqli_stmt_get_result'))
|
||||
if (!mysqli_stmt_execute($stmt))
|
||||
printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
|
||||
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
try {
|
||||
$res = mysqli_stmt_get_result($stmt);
|
||||
// we expect no segfault if we try to fetch a row because get_result should throw an error or return false
|
||||
mysqli_fetch_assoc($res);
|
||||
} catch (\mysqli_sql_exception $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
$result = mysqli_stmt_get_result($stmt);
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
var_dump($row);
|
||||
}
|
||||
|
||||
try {
|
||||
$res = $stmt->get_result();
|
||||
// we expect no segfault if we try to fetch a row because get_result should throw an error or return false
|
||||
$res->fetch_assoc();
|
||||
} catch (\mysqli_sql_exception $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
mysqli_report(MYSQLI_REPORT_OFF);
|
||||
|
||||
if (!$stmt = mysqli_stmt_init($link))
|
||||
printf("[034] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
|
||||
@@ -213,8 +186,18 @@ Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
|
||||
|
||||
Warning: mysqli_stmt_get_result(): invalid object or resource mysqli_stmt
|
||||
in %s on line %d
|
||||
mysqli_stmt_get_result() cannot be used with cursors
|
||||
get_result() cannot be used with cursors
|
||||
array(2) {
|
||||
["id"]=>
|
||||
int(1)
|
||||
["label"]=>
|
||||
string(1) "a"
|
||||
}
|
||||
array(2) {
|
||||
["id"]=>
|
||||
int(2)
|
||||
["label"]=>
|
||||
string(1) "b"
|
||||
}
|
||||
[040] [2014] [Commands out of sync; you can't run this command now]
|
||||
[041] [0] []
|
||||
array(2) {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
--TEST--
|
||||
PS using cursor and returning multiple result sets
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once('skipif.inc');
|
||||
require_once('skipifconnectfailure.inc');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once(__DIR__ . '/connect.inc');
|
||||
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
$db = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
|
||||
$db->query('DROP PROCEDURE IF EXISTS testPs');
|
||||
$db->query(<<<'SQL'
|
||||
CREATE PROCEDURE testPs() BEGIN
|
||||
DECLARE testCursor CURSOR FOR SELECT 'stuff';
|
||||
OPEN testCursor;
|
||||
CLOSE testCursor;
|
||||
SELECT 1 as a, 2 as b;
|
||||
SELECT 3 as a, 4 as b;
|
||||
END
|
||||
SQL
|
||||
);
|
||||
|
||||
echo "use_result:\n";
|
||||
$stmt = $db->prepare("call testPs()");
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($v1, $v2);
|
||||
while ($stmt->fetch()) {
|
||||
var_dump($v1, $v2);
|
||||
}
|
||||
|
||||
$stmt->next_result();
|
||||
$stmt->bind_result($v1, $v2);
|
||||
while ($stmt->fetch()) {
|
||||
var_dump($v1, $v2);
|
||||
}
|
||||
$stmt->next_result();
|
||||
|
||||
echo "\nstore_result:\n";
|
||||
$stmt = $db->prepare("call testPs()");
|
||||
$stmt->execute();
|
||||
$stmt->store_result();
|
||||
$stmt->bind_result($v1, $v2);
|
||||
while ($stmt->fetch()) {
|
||||
var_dump($v1, $v2);
|
||||
}
|
||||
|
||||
$stmt->next_result();
|
||||
$stmt->store_result();
|
||||
$stmt->bind_result($v1, $v2);
|
||||
while ($stmt->fetch()) {
|
||||
var_dump($v1, $v2);
|
||||
}
|
||||
$stmt->next_result();
|
||||
|
||||
echo "\nget_result:\n";
|
||||
$stmt = $db->prepare("call testPs()");
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
var_dump($row);
|
||||
}
|
||||
|
||||
$stmt->next_result();
|
||||
$result = $stmt->get_result();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
var_dump($row);
|
||||
}
|
||||
$stmt->next_result();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
use_result:
|
||||
int(1)
|
||||
int(2)
|
||||
int(3)
|
||||
int(4)
|
||||
|
||||
store_result:
|
||||
int(1)
|
||||
int(2)
|
||||
int(3)
|
||||
int(4)
|
||||
|
||||
get_result:
|
||||
array(2) {
|
||||
["a"]=>
|
||||
int(1)
|
||||
["b"]=>
|
||||
int(2)
|
||||
}
|
||||
array(2) {
|
||||
["a"]=>
|
||||
int(3)
|
||||
["b"]=>
|
||||
int(4)
|
||||
}
|
||||
+71
-58
@@ -40,6 +40,36 @@ enum_func_status mysqlnd_stmt_execute_batch_generate_request(MYSQLND_STMT * cons
|
||||
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt);
|
||||
static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, const unsigned int param_no);
|
||||
|
||||
static enum_func_status mysqlnd_stmt_send_cursor_fetch_command(
|
||||
const MYSQLND_STMT_DATA *stmt, unsigned max_rows)
|
||||
{
|
||||
MYSQLND_CONN_DATA *conn = stmt->conn;
|
||||
zend_uchar buf[MYSQLND_STMT_ID_LENGTH /* statement id */ + 4 /* number of rows to fetch */];
|
||||
const MYSQLND_CSTRING payload = {(const char*) buf, sizeof(buf)};
|
||||
|
||||
int4store(buf, stmt->stmt_id);
|
||||
int4store(buf + MYSQLND_STMT_ID_LENGTH, max_rows);
|
||||
|
||||
if (conn->command->stmt_fetch(conn, payload) == FAIL) {
|
||||
COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
|
||||
return FAIL;
|
||||
}
|
||||
return PASS;
|
||||
}
|
||||
|
||||
static zend_bool mysqlnd_stmt_check_state(const MYSQLND_STMT_DATA *stmt)
|
||||
{
|
||||
const MYSQLND_CONN_DATA *conn = stmt->conn;
|
||||
if (stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
|
||||
return 0;
|
||||
}
|
||||
if (stmt->cursor_exists) {
|
||||
return GET_CONNECTION_STATE(&conn->state) == CONN_READY;
|
||||
} else {
|
||||
return GET_CONNECTION_STATE(&conn->state) == CONN_FETCHING_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ mysqlnd_stmt::store_result */
|
||||
static MYSQLND_RES *
|
||||
MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
|
||||
@@ -60,14 +90,8 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
if (stmt->cursor_exists) {
|
||||
/* Silently convert buffered to unbuffered, for now */
|
||||
DBG_RETURN(s->m->use_result(s));
|
||||
}
|
||||
|
||||
/* Nothing to store for UPSERT/LOAD DATA*/
|
||||
if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
if (!mysqlnd_stmt_check_state(stmt)) {
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
@@ -78,6 +102,12 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
|
||||
SET_EMPTY_ERROR(conn->error_info);
|
||||
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_BUFFERED_SETS);
|
||||
|
||||
if (stmt->cursor_exists) {
|
||||
if (mysqlnd_stmt_send_cursor_fetch_command(stmt, -1) == FAIL) {
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
result = stmt->result;
|
||||
result->type = MYSQLND_RES_PS_BUF;
|
||||
/* result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; */
|
||||
@@ -152,19 +182,8 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
if (stmt->cursor_exists) {
|
||||
/* Prepared statement cursors are not supported as of yet */
|
||||
char * msg;
|
||||
mnd_sprintf(&msg, 0, "%s() cannot be used with cursors", get_active_function_name());
|
||||
SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, msg);
|
||||
if (msg) {
|
||||
mnd_sprintf_free(msg);
|
||||
}
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
|
||||
/* Nothing to store for UPSERT/LOAD DATA*/
|
||||
if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
|
||||
if (!mysqlnd_stmt_check_state(stmt)) {
|
||||
SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
@@ -173,6 +192,12 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
|
||||
SET_EMPTY_ERROR(conn->error_info);
|
||||
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
|
||||
|
||||
if (stmt->cursor_exists) {
|
||||
if (mysqlnd_stmt_send_cursor_fetch_command(stmt, -1) == FAIL) {
|
||||
DBG_RETURN(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
result = conn->m->result_init(stmt->result->field_count);
|
||||
if (!result) {
|
||||
@@ -561,28 +586,30 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
|
||||
DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status),
|
||||
UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS);
|
||||
|
||||
if (UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS) {
|
||||
DBG_INF("cursor exists");
|
||||
stmt->cursor_exists = TRUE;
|
||||
SET_CONNECTION_STATE(&conn->state, CONN_READY);
|
||||
/* Only cursor read */
|
||||
stmt->default_rset_handler = s->m->use_result;
|
||||
DBG_INF("use_result");
|
||||
} else if (stmt->flags & CURSOR_TYPE_READ_ONLY) {
|
||||
DBG_INF("asked for cursor but got none");
|
||||
/*
|
||||
We have asked for CURSOR but got no cursor, because the condition
|
||||
above is not fulfilled. Then...
|
||||
if (stmt->flags & CURSOR_TYPE_READ_ONLY) {
|
||||
if (UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS) {
|
||||
DBG_INF("cursor exists");
|
||||
stmt->cursor_exists = TRUE;
|
||||
SET_CONNECTION_STATE(&conn->state, CONN_READY);
|
||||
/* Only cursor read */
|
||||
stmt->default_rset_handler = s->m->use_result;
|
||||
DBG_INF("use_result");
|
||||
} else {
|
||||
DBG_INF("asked for cursor but got none");
|
||||
/*
|
||||
We have asked for CURSOR but got no cursor, because the condition
|
||||
above is not fulfilled. Then...
|
||||
|
||||
This is a single-row result set, a result set with no rows, EXPLAIN,
|
||||
SHOW VARIABLES, or some other command which either a) bypasses the
|
||||
cursors framework in the server and writes rows directly to the
|
||||
network or b) is more efficient if all (few) result set rows are
|
||||
precached on client and server's resources are freed.
|
||||
*/
|
||||
/* preferred is buffered read */
|
||||
stmt->default_rset_handler = s->m->store_result;
|
||||
DBG_INF("store_result");
|
||||
This is a single-row result set, a result set with no rows, EXPLAIN,
|
||||
SHOW VARIABLES, or some other command which either a) bypasses the
|
||||
cursors framework in the server and writes rows directly to the
|
||||
network or b) is more efficient if all (few) result set rows are
|
||||
precached on client and server's resources are freed.
|
||||
*/
|
||||
/* preferred is buffered read */
|
||||
stmt->default_rset_handler = s->m->store_result;
|
||||
DBG_INF("store_result");
|
||||
}
|
||||
} else {
|
||||
DBG_INF("no cursor");
|
||||
/* preferred is unbuffered read */
|
||||
@@ -940,11 +967,7 @@ MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s)
|
||||
}
|
||||
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
|
||||
|
||||
if (!stmt->field_count ||
|
||||
(!stmt->cursor_exists && GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) ||
|
||||
(stmt->cursor_exists && GET_CONNECTION_STATE(&conn->state) != CONN_READY) ||
|
||||
(stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE))
|
||||
{
|
||||
if (!stmt->field_count || !mysqlnd_stmt_check_state(stmt)) {
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
|
||||
DBG_ERR("command out of sync");
|
||||
DBG_RETURN(NULL);
|
||||
@@ -974,7 +997,6 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned
|
||||
MYSQLND_STMT * s = (MYSQLND_STMT *) param;
|
||||
MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
|
||||
MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
|
||||
zend_uchar buf[MYSQLND_STMT_ID_LENGTH /* statement id */ + 4 /* number of rows to fetch */];
|
||||
MYSQLND_PACKET_ROW * row_packet;
|
||||
|
||||
DBG_ENTER("mysqlnd_fetch_stmt_row_cursor");
|
||||
@@ -998,18 +1020,9 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned
|
||||
SET_EMPTY_ERROR(stmt->error_info);
|
||||
SET_EMPTY_ERROR(conn->error_info);
|
||||
|
||||
int4store(buf, stmt->stmt_id);
|
||||
int4store(buf + MYSQLND_STMT_ID_LENGTH, 1); /* for now fetch only one row */
|
||||
|
||||
{
|
||||
const MYSQLND_CSTRING payload = {(const char*) buf, sizeof(buf)};
|
||||
|
||||
ret = conn->command->stmt_fetch(conn, payload);
|
||||
if (ret == FAIL) {
|
||||
COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
/* for now fetch only one row */
|
||||
if (mysqlnd_stmt_send_cursor_fetch_command(stmt, 1) == FAIL) {
|
||||
DBG_RETURN(FAIL);
|
||||
}
|
||||
|
||||
row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE;
|
||||
|
||||
@@ -1616,8 +1616,28 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
|
||||
}
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, statistic, 1, STAT_BYTES_RECEIVED_PURE_DATA_TEXT, len);
|
||||
}
|
||||
if (fields_metadata[i].type == MYSQL_TYPE_BIT) {
|
||||
/*
|
||||
BIT fields are specially handled. As they come as bit mask, they have
|
||||
to be converted to human-readable representation.
|
||||
*/
|
||||
ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, (const zend_uchar **) &p, len);
|
||||
/*
|
||||
We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
|
||||
later in this function there will be an advancement.
|
||||
*/
|
||||
p -= len;
|
||||
if (Z_TYPE_P(current_field) == IS_LONG && !as_int_or_float) {
|
||||
/* we are using the text protocol, so convert to string */
|
||||
char tmp[22];
|
||||
const size_t tmp_len = sprintf((char *)&tmp, ZEND_ULONG_FMT, Z_LVAL_P(current_field));
|
||||
ZVAL_STRINGL(current_field, tmp, tmp_len);
|
||||
} else if (Z_TYPE_P(current_field) == IS_STRING) {
|
||||
/* nothing to do here, as we want a string and ps_fetch_from_1_to_8_bytes() has given us one */
|
||||
}
|
||||
}
|
||||
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
|
||||
if (as_int_or_float && perm_bind.php_type == IS_LONG) {
|
||||
else if (as_int_or_float && perm_bind.php_type == IS_LONG) {
|
||||
zend_uchar save = *(p + len);
|
||||
/* We have to make it ASCIIZ temporarily */
|
||||
*(p + len) = '\0';
|
||||
@@ -1661,28 +1681,9 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
|
||||
*(p + len) = '\0';
|
||||
ZVAL_DOUBLE(current_field, atof((char *) p));
|
||||
*(p + len) = save;
|
||||
} else
|
||||
}
|
||||
#endif /* MYSQLND_STRING_TO_INT_CONVERSION */
|
||||
if (fields_metadata[i].type == MYSQL_TYPE_BIT) {
|
||||
/*
|
||||
BIT fields are specially handled. As they come as bit mask, they have
|
||||
to be converted to human-readable representation.
|
||||
*/
|
||||
ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, (const zend_uchar **) &p, len);
|
||||
/*
|
||||
We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
|
||||
later in this function there will be an advancement.
|
||||
*/
|
||||
p -= len;
|
||||
if (Z_TYPE_P(current_field) == IS_LONG && !as_int_or_float) {
|
||||
/* we are using the text protocol, so convert to string */
|
||||
char tmp[22];
|
||||
const size_t tmp_len = sprintf((char *)&tmp, ZEND_ULONG_FMT, Z_LVAL_P(current_field));
|
||||
ZVAL_STRINGL(current_field, tmp, tmp_len);
|
||||
} else if (Z_TYPE_P(current_field) == IS_STRING) {
|
||||
/* nothing to do here, as we want a string and ps_fetch_from_1_to_8_bytes() has given us one */
|
||||
}
|
||||
} else if (len == 0) {
|
||||
else if (len == 0) {
|
||||
ZVAL_EMPTY_STRING(current_field);
|
||||
} else if (len == 1) {
|
||||
ZVAL_INTERNED_STR(current_field, ZSTR_CHAR((zend_uchar)*(char *)p));
|
||||
|
||||
+18
-20
@@ -609,7 +609,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
if (NULL == (z_script_name = zend_hash_str_find(_server, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) ||
|
||||
IS_STRING != Z_TYPE_P(z_script_name) ||
|
||||
!strstr(Z_STRVAL_P(z_script_name), basename)) {
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (NULL != (z_path_info = zend_hash_str_find(_server, "PATH_INFO", sizeof("PATH_INFO")-1)) &&
|
||||
@@ -634,7 +634,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1);
|
||||
if (!(pt = strstr(testit, basename))) {
|
||||
efree(testit);
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1);
|
||||
@@ -659,7 +659,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
|
||||
if (!(pt = strstr(path_info, basename))) {
|
||||
/* this can happen with rewrite rules - and we have no idea what to do then, so return */
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
entry_len = strlen(path_info);
|
||||
@@ -685,7 +685,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
}
|
||||
efree(pt);
|
||||
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
fci.param_count = 1;
|
||||
@@ -703,7 +703,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
}
|
||||
efree(pt);
|
||||
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(fci.retval) == IS_UNDEF || Z_TYPE(retval) == IS_UNDEF) {
|
||||
@@ -712,7 +712,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
}
|
||||
zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
|
||||
efree(pt);
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
switch (Z_TYPE(retval)) {
|
||||
@@ -731,7 +731,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
efree(pt);
|
||||
|
||||
zend_bailout();
|
||||
return;
|
||||
goto finish;
|
||||
default:
|
||||
if (free_pathinfo) {
|
||||
efree(path_info);
|
||||
@@ -739,7 +739,7 @@ PHP_METHOD(Phar, webPhar)
|
||||
efree(pt);
|
||||
|
||||
zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
|
||||
return;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -812,9 +812,6 @@ PHP_METHOD(Phar, webPhar)
|
||||
if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
|
||||
(info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
|
||||
phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
|
||||
#ifdef PHP_WIN32
|
||||
efree(fname);
|
||||
#endif
|
||||
zend_bailout();
|
||||
}
|
||||
|
||||
@@ -838,10 +835,8 @@ PHP_METHOD(Phar, webPhar)
|
||||
}
|
||||
efree(pt);
|
||||
efree(entry);
|
||||
#ifdef PHP_WIN32
|
||||
efree(fname);
|
||||
#endif
|
||||
RETURN_FALSE;
|
||||
RETVAL_FALSE;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case IS_STRING:
|
||||
@@ -855,10 +850,8 @@ PHP_METHOD(Phar, webPhar)
|
||||
}
|
||||
efree(pt);
|
||||
efree(entry);
|
||||
#ifdef PHP_WIN32
|
||||
efree(fname);
|
||||
#endif
|
||||
RETURN_FALSE;
|
||||
RETVAL_FALSE;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -868,6 +861,11 @@ PHP_METHOD(Phar, webPhar)
|
||||
code = phar_file_type(&PHAR_G(mime_types), entry, &mime_type);
|
||||
}
|
||||
phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len);
|
||||
|
||||
finish: ;
|
||||
#ifdef PHP_WIN32
|
||||
efree(fname);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -4277,7 +4275,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (!phar_get_efp(entry, 0)) {
|
||||
if ((phar_get_fp_type(entry) == PHAR_FP && (entry->flags & PHAR_ENT_COMPRESSION_MASK)) || !phar_get_efp(entry, 0)) {
|
||||
if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('phar')) die('skip phar extension not available');
|
||||
?>
|
||||
--INI--
|
||||
phar.readonly=0
|
||||
--FILE--
|
||||
<?php
|
||||
$w = new Phar(__DIR__ . "/bug69279.phar.zip");
|
||||
$w["bug69279.txt"] = "Sample content.";
|
||||
$w->compressFiles(Phar::GZ);
|
||||
unset($w);
|
||||
|
||||
$r = new Phar(__DIR__ . "/bug69279.phar.zip");
|
||||
var_dump($r["bug69279.txt"]->isCompressed());
|
||||
|
||||
$r->extractTo(__DIR__, NULL, TRUE);
|
||||
var_dump(file_get_contents(__DIR__ . "/bug69279.txt"));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
string(15) "Sample content."
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__ . "/bug69279.txt");
|
||||
@unlink(__DIR__ . "/bug69279.phar.zip");
|
||||
?>
|
||||
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('phar')) die('skip phar extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$phar = new PharData(__DIR__ . '/bug69279a.zip');
|
||||
mkdir(__DIR__ . '/bug69279a');
|
||||
var_dump($phar->extractTo(__DIR__ . '/bug69279a', null, true));
|
||||
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/1.txt'), 'Lorem ipsum', 11));
|
||||
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/2.txt'), 'foo', 3));
|
||||
var_dump(strncmp(file_get_contents(__DIR__ . '/bug69279a/3.txt'), 'Lorem ipsum', 11));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
int(0)
|
||||
int(0)
|
||||
int(0)
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__ . '/bug69279a/1.txt');
|
||||
@unlink(__DIR__ . '/bug69279a/2.txt');
|
||||
@unlink(__DIR__ . '/bug69279a/3.txt');
|
||||
@rmdir(__DIR__ . '/bug69279a');
|
||||
Binary file not shown.
@@ -14,7 +14,7 @@ $r = new Phar($fname, 0);
|
||||
|
||||
==DONE==
|
||||
--EXPECTF--
|
||||
UnexpectedValueException: phar error: corrupted central directory entry, no magic signature in zip-based phar "%sbug69441.phar" in %sbug69441.php:%d
|
||||
UnexpectedValueException: phar error: end of central directory not found in zip-based phar "%sbug69441.phar" in %sbug69441.php:%d
|
||||
Stack trace:
|
||||
#0 %s%ebug69441.php(%d): Phar->__construct('%s', 0)
|
||||
#1 {main}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Bug #77565 (Incorrect locator detection in ZIP-based phars)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('phar')) die('skip phar extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$phar = new PharData(__DIR__ . '/bug77565.zip');
|
||||
var_dump($phar['1.zip']->getFilename());
|
||||
?>
|
||||
--EXPECT--
|
||||
string(5) "1.zip"
|
||||
Binary file not shown.
@@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
Bug #79912 (Phar::decompressFiles not working)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('phar')) die('skip phar extension is not available');
|
||||
?>
|
||||
--INI--
|
||||
phar.readonly=0
|
||||
--FILE--
|
||||
<?php
|
||||
$phar = new Phar(__DIR__ . "/bug79912.phar");
|
||||
$phar->addFromString("test.txt", "This is a test file.This is a test file.This is a test file.");
|
||||
$file = $phar["test.txt"];
|
||||
var_dump($file->compress(Phar::GZ)); //true (success)
|
||||
var_dump($file->getContent());
|
||||
var_dump($file->isCompressed()); //true (the file is compressed)
|
||||
var_dump($phar->decompressFiles()); //true (success)
|
||||
var_dump($file->isCompressed()); //false (the file should not be compressed anymore)
|
||||
var_dump($phar->extractTo(__DIR__ . "/bug79912")); //true
|
||||
var_dump(file_get_contents(__DIR__ . "/bug79912/test.txt")); //the extracted file in the folder should be decompressed
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
string(60) "This is a test file.This is a test file.This is a test file."
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
string(60) "This is a test file.This is a test file.This is a test file."
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__ . "/bug79912/test.txt");
|
||||
@rmdir(__DIR__ . "/bug79912");
|
||||
@unlink(__DIR__ . "/bug79912.phar");
|
||||
?>
|
||||
@@ -12,5 +12,5 @@ try {
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
phar error: corrupt zip archive, zip file comment truncated in zip-based phar "%sfilecomment.zip"
|
||||
phar error: end of central directory not found in zip-based phar "%sfilecomment.zip"
|
||||
===DONE===
|
||||
+70
-49
@@ -161,6 +161,29 @@ static void phar_zip_u2d_time(time_t time, char *dtime, char *ddate) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static char *phar_find_eocd(const char *s, size_t n)
|
||||
{
|
||||
const char *end = s + n + sizeof("PK\5\6") - 1 - sizeof(phar_zip_dir_end);
|
||||
|
||||
/* search backwards for end of central directory signatures */
|
||||
do {
|
||||
uint16_t comment_len;
|
||||
const char *eocd_start = zend_memnrstr(s, "PK\5\6", sizeof("PK\5\6") - 1, end);
|
||||
|
||||
if (eocd_start == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZEND_ASSERT(eocd_start + sizeof(phar_zip_dir_end) <= s + n);
|
||||
comment_len = PHAR_GET_16(((phar_zip_dir_end *) eocd_start)->comment_len);
|
||||
if (eocd_start + sizeof(phar_zip_dir_end) + comment_len == s + n) {
|
||||
/* we can't be sure, but this looks like the proper EOCD signature */
|
||||
return (char *) eocd_start;
|
||||
}
|
||||
end = eocd_start;
|
||||
} while (end > s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not check for a previously opened phar in the cache.
|
||||
*
|
||||
@@ -205,57 +228,55 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while ((p=(char *) memchr(p + 1, 'P', (size_t) (size - (p + 1 - buf)))) != NULL) {
|
||||
if ((p - buf) + sizeof(locator) <= (size_t)size && !memcmp(p + 1, "K\5\6", 3)) {
|
||||
memcpy((void *)&locator, (void *) p, sizeof(locator));
|
||||
if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) {
|
||||
/* split archives not handled */
|
||||
php_stream_close(fp);
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
return FAILURE;
|
||||
if ((p = phar_find_eocd(buf, size)) != NULL) {
|
||||
memcpy((void *)&locator, (void *) p, sizeof(locator));
|
||||
if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) {
|
||||
/* split archives not handled */
|
||||
php_stream_close(fp);
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
|
||||
if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
|
||||
mydata->is_persistent = PHAR_G(persist);
|
||||
|
||||
/* read in archive comment, if any */
|
||||
if (PHAR_GET_16(locator.comment_len)) {
|
||||
|
||||
metadata = p + sizeof(locator);
|
||||
|
||||
if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
pefree(mydata, mydata->is_persistent);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata->metadata_len = PHAR_GET_16(locator.comment_len);
|
||||
|
||||
if (phar_parse_metadata(&metadata, &mydata->metadata, PHAR_GET_16(locator.comment_len)) == FAILURE) {
|
||||
mydata->metadata_len = 0;
|
||||
/* if not valid serialized data, it is a regular string */
|
||||
|
||||
ZVAL_NEW_STR(&mydata->metadata, zend_string_init(metadata, PHAR_GET_16(locator.comment_len), mydata->is_persistent));
|
||||
}
|
||||
} else {
|
||||
ZVAL_UNDEF(&mydata->metadata);
|
||||
}
|
||||
|
||||
goto foundit;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
|
||||
mydata->is_persistent = PHAR_G(persist);
|
||||
|
||||
/* read in archive comment, if any */
|
||||
if (PHAR_GET_16(locator.comment_len)) {
|
||||
|
||||
metadata = p + sizeof(locator);
|
||||
|
||||
if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) {
|
||||
if (error) {
|
||||
spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
|
||||
}
|
||||
php_stream_close(fp);
|
||||
pefree(mydata, mydata->is_persistent);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
mydata->metadata_len = PHAR_GET_16(locator.comment_len);
|
||||
|
||||
if (phar_parse_metadata(&metadata, &mydata->metadata, PHAR_GET_16(locator.comment_len)) == FAILURE) {
|
||||
mydata->metadata_len = 0;
|
||||
/* if not valid serialized data, it is a regular string */
|
||||
|
||||
ZVAL_NEW_STR(&mydata->metadata, zend_string_init(metadata, PHAR_GET_16(locator.comment_len), mydata->is_persistent));
|
||||
}
|
||||
} else {
|
||||
ZVAL_UNDEF(&mydata->metadata);
|
||||
}
|
||||
|
||||
goto foundit;
|
||||
}
|
||||
|
||||
php_stream_close(fp);
|
||||
|
||||
@@ -555,6 +555,7 @@ static char **_readline_completion_cb(const char *text, int start, int end)
|
||||
|
||||
if (call_user_function(NULL, NULL, &_readline_completion, &_readline_array, 3, params) == SUCCESS) {
|
||||
if (Z_TYPE(_readline_array) == IS_ARRAY) {
|
||||
SEPARATE_ARRAY(&_readline_array);
|
||||
if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) {
|
||||
matches = rl_completion_matches(text,_readline_command_generator);
|
||||
} else {
|
||||
|
||||
+1
-5
@@ -831,10 +831,6 @@ PHP_FUNCTION(tempnam)
|
||||
Z_PARAM_PATH(prefix, prefix_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (php_check_open_basedir(dir)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
p = php_basename(prefix, prefix_len, NULL, 0);
|
||||
if (ZSTR_LEN(p) > 64) {
|
||||
ZSTR_VAL(p)[63] = '\0';
|
||||
@@ -842,7 +838,7 @@ PHP_FUNCTION(tempnam)
|
||||
|
||||
RETVAL_FALSE;
|
||||
|
||||
if ((fd = php_open_temporary_fd_ex(dir, ZSTR_VAL(p), &opened_path, 1)) >= 0) {
|
||||
if ((fd = php_open_temporary_fd_ex(dir, ZSTR_VAL(p), &opened_path, PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ALWAYS)) >= 0) {
|
||||
close(fd);
|
||||
RETVAL_STR(opened_path);
|
||||
}
|
||||
|
||||
@@ -53,17 +53,17 @@ var_dump( $temp_array);
|
||||
|
||||
echo "\n-- Testing ksort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
|
||||
$temp_array = $unsorted_strings;
|
||||
var_dump( sort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
|
||||
var_dump( ksort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
|
||||
var_dump( $temp_array);
|
||||
|
||||
echo "\n-- Testing ksort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
|
||||
$temp_array = $unsorted_strings;
|
||||
var_dump( sort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
|
||||
var_dump( ksort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
|
||||
var_dump( $temp_array);
|
||||
|
||||
echo "\n-- Testing ksort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
|
||||
$temp_array = $unsorted_strings;
|
||||
var_dump( sort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
|
||||
var_dump( ksort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
|
||||
var_dump( $temp_array);
|
||||
|
||||
echo "\n-- Testing ksort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
|
||||
@@ -168,63 +168,63 @@ array(8) {
|
||||
-- Testing ksort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
|
||||
bool(true)
|
||||
array(8) {
|
||||
[0]=>
|
||||
["b"]=>
|
||||
string(6) "banana"
|
||||
[1]=>
|
||||
["l"]=>
|
||||
string(5) "lemon"
|
||||
[2]=>
|
||||
["o"]=>
|
||||
string(6) "orange"
|
||||
[3]=>
|
||||
["O"]=>
|
||||
string(6) "Orange"
|
||||
[4]=>
|
||||
["O1"]=>
|
||||
string(7) "Orange1"
|
||||
[5]=>
|
||||
["o2"]=>
|
||||
string(7) "orange2"
|
||||
[6]=>
|
||||
["o20"]=>
|
||||
string(8) "orange20"
|
||||
[7]=>
|
||||
["O3"]=>
|
||||
string(7) "Orange3"
|
||||
}
|
||||
|
||||
-- Testing ksort() by supplying string array (natural), 'flag' = SORT_NATURAL --
|
||||
bool(true)
|
||||
array(8) {
|
||||
[0]=>
|
||||
["O"]=>
|
||||
string(6) "Orange"
|
||||
[1]=>
|
||||
["O1"]=>
|
||||
string(7) "Orange1"
|
||||
[2]=>
|
||||
["O3"]=>
|
||||
string(7) "Orange3"
|
||||
[3]=>
|
||||
["b"]=>
|
||||
string(6) "banana"
|
||||
[4]=>
|
||||
["l"]=>
|
||||
string(5) "lemon"
|
||||
[5]=>
|
||||
["o"]=>
|
||||
string(6) "orange"
|
||||
[6]=>
|
||||
["o2"]=>
|
||||
string(7) "orange2"
|
||||
[7]=>
|
||||
["o20"]=>
|
||||
string(8) "orange20"
|
||||
}
|
||||
|
||||
-- Testing ksort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
|
||||
bool(true)
|
||||
array(8) {
|
||||
[0]=>
|
||||
["b"]=>
|
||||
string(6) "banana"
|
||||
[1]=>
|
||||
["l"]=>
|
||||
string(5) "lemon"
|
||||
[2]=>
|
||||
["o"]=>
|
||||
string(6) "orange"
|
||||
[3]=>
|
||||
["O"]=>
|
||||
string(6) "Orange"
|
||||
[4]=>
|
||||
["O1"]=>
|
||||
string(7) "Orange1"
|
||||
[5]=>
|
||||
["o2"]=>
|
||||
string(7) "orange2"
|
||||
[6]=>
|
||||
["O3"]=>
|
||||
string(7) "Orange3"
|
||||
[7]=>
|
||||
["o20"]=>
|
||||
string(8) "orange20"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Bug #42560 Empty directory argument to tempnam yields open_basedir problems
|
||||
--FILE--
|
||||
<?php
|
||||
$tmpdir = sys_get_temp_dir();
|
||||
ini_set('open_basedir', $tmpdir);
|
||||
$tempnam = tempnam('', 'test');
|
||||
var_dump($tempnam !== false);
|
||||
var_dump(file_exists($tempnam));
|
||||
|
||||
if (file_exists($tempnam)) {
|
||||
unlink($tempnam);
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(true)
|
||||
@@ -52,6 +52,6 @@ fclose($f2);
|
||||
--EXPECT--
|
||||
filter onCreate
|
||||
filtered 8192 bytes.
|
||||
filtered 128 bytes and closing.
|
||||
filtered 128 bytes and closing. Stream has reached end-of-file.
|
||||
int(8320)
|
||||
filter onClose
|
||||
@@ -301,13 +301,19 @@ PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_strin
|
||||
def_tmp:
|
||||
temp_dir = php_get_temporary_directory();
|
||||
|
||||
if (temp_dir && *temp_dir != '\0' && (!(flags & PHP_TMP_FILE_OPEN_BASEDIR_CHECK) || !php_check_open_basedir(temp_dir))) {
|
||||
if (temp_dir &&
|
||||
*temp_dir != '\0' &&
|
||||
(!(flags & PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK) || !php_check_open_basedir(temp_dir))) {
|
||||
return php_do_open_temporary_file(temp_dir, pfx, opened_path_p);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_EXPLICIT_DIR) && php_check_open_basedir(dir)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try the directory given as parameter. */
|
||||
fd = php_do_open_temporary_file(dir, pfx, opened_path_p);
|
||||
if (fd == -1) {
|
||||
@@ -322,7 +328,7 @@ def_tmp:
|
||||
|
||||
PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p)
|
||||
{
|
||||
return php_open_temporary_fd_ex(dir, pfx, opened_path_p, 0);
|
||||
return php_open_temporary_fd_ex(dir, pfx, opened_path_p, PHP_TMP_FILE_DEFAULT);
|
||||
}
|
||||
|
||||
PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_p)
|
||||
|
||||
@@ -19,8 +19,16 @@
|
||||
#ifndef PHP_OPEN_TEMPORARY_FILE_H
|
||||
#define PHP_OPEN_TEMPORARY_FILE_H
|
||||
|
||||
#define PHP_TMP_FILE_OPEN_BASEDIR_CHECK (1<<0)
|
||||
#define PHP_TMP_FILE_DEFAULT 0
|
||||
#define PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK (1<<0)
|
||||
#define PHP_TMP_FILE_SILENT (1<<1)
|
||||
#define PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_EXPLICIT_DIR (1<<2)
|
||||
#define PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ALWAYS \
|
||||
(PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK | PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_EXPLICIT_DIR)
|
||||
|
||||
/* for compatibility purpose */
|
||||
#define PHP_TMP_FILE_OPEN_BASEDIR_CHECK PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK
|
||||
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_p);
|
||||
|
||||
+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 14
|
||||
#define PHP_EXTRA_VERSION ""
|
||||
#define PHP_VERSION "7.4.14"
|
||||
#define PHP_VERSION_ID 70414
|
||||
#define PHP_RELEASE_VERSION 15
|
||||
#define PHP_EXTRA_VERSION "RC2"
|
||||
#define PHP_VERSION "7.4.15RC2"
|
||||
#define PHP_VERSION_ID 70415
|
||||
+1
-1
@@ -1009,7 +1009,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
|
||||
/* in non-debug mode we have no problem with 0-length files */
|
||||
{
|
||||
#endif
|
||||
fd = php_open_temporary_fd_ex(PG(upload_tmp_dir), "php", &temp_filename, 1);
|
||||
fd = php_open_temporary_fd_ex(PG(upload_tmp_dir), "php", &temp_filename, PHP_TMP_FILE_OPEN_BASEDIR_CHECK_ON_FALLBACK);
|
||||
upload_cnt--;
|
||||
if (fd == -1) {
|
||||
sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file");
|
||||
|
||||
@@ -542,6 +542,7 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
|
||||
/* allocate/fill the buffer */
|
||||
|
||||
if (stream->readfilters.head) {
|
||||
size_t to_read_now = MIN(size, stream->chunk_size);
|
||||
char *chunk_buf;
|
||||
php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL };
|
||||
php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap;
|
||||
@@ -549,7 +550,7 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
|
||||
/* allocate a buffer for reading chunks */
|
||||
chunk_buf = emalloc(stream->chunk_size);
|
||||
|
||||
while (!stream->eof && (stream->writepos - stream->readpos < (zend_off_t)size)) {
|
||||
while (!stream->eof && (stream->writepos - stream->readpos < (zend_off_t)to_read_now)) {
|
||||
ssize_t justread = 0;
|
||||
int flags;
|
||||
php_stream_bucket *bucket;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
Bug #80384 large reads cause filters to internally buffer large amounts of memory
|
||||
--FILE--
|
||||
<?php
|
||||
/* First, create a file to read */
|
||||
$tmp_filename = __DIR__ . "/bug80384.tmp";
|
||||
$fp = fopen($tmp_filename, 'w');
|
||||
for ($i=0; $i<1024; $i++) {
|
||||
fwrite($fp, str_repeat('ABCDEFGH', 1024));
|
||||
}
|
||||
fclose($fp);
|
||||
|
||||
/* Stream the file through a filter */
|
||||
$fp = fopen($tmp_filename, 'r');
|
||||
$filter = stream_filter_append($fp, "string.rot13");
|
||||
|
||||
$mem_start = memory_get_usage();
|
||||
fread($fp, 8 * 1024 * 1024);
|
||||
$mem_final = memory_get_usage();
|
||||
fclose($fp);
|
||||
var_dump($mem_final - $mem_start < 32768);
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
unlink(__DIR__ . "/bug80384.tmp");
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
@@ -63,7 +63,7 @@ bool(false)
|
||||
Warning: tempnam(): open_basedir restriction in effect. File(./../.) is not within the allowed path(s): (.) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: tempnam(): open_basedir restriction in effect. File() is not within the allowed path(s): (.) in %s on line %d
|
||||
Warning: tempnam(): open_basedir restriction in effect. File(%s) is not within the allowed path(s): (.) in %s on line %d
|
||||
bool(false)
|
||||
string(%d) "%s"
|
||||
bool(true)
|
||||
|
||||
Reference in new issue
Block a user