summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarek Slusarczyk <dariusz.slusarczyk@oracle.com>2019-02-11 18:08:21 +0100
committerDarek Slusarczyk <dariusz.slusarczyk@oracle.com>2019-02-11 18:08:21 +0100
commit83d2bc9b6df2f827217f1bc3298fb83cfe2ac210 (patch)
treed511c4d57e63ff0d0de4e8f17783d62e6deb224b
parentec28d4c247ef3c7ab9af41ff6e26b802694492b2 (diff)
parent2eaabf06fc5a62104ecb597830b2852d71b0a111 (diff)
downloadphp-git-83d2bc9b6df2f827217f1bc3298fb83cfe2ac210.tar.gz
Merge branch 'PHP-7.1' into PHP-7.2
-rw-r--r--NEWS5
-rw-r--r--ext/mysqli/mysqli.c4
-rw-r--r--ext/mysqli/tests/061.phpt2
-rw-r--r--ext/mysqli/tests/bug36745.phpt2
-rw-r--r--ext/mysqli/tests/bug53503.phpt2
-rw-r--r--ext/mysqli/tests/bug68077.phpt3
-rw-r--r--ext/mysqli/tests/mysqli_constants.phpt2
-rw-r--r--ext/mysqli/tests/mysqli_get_client_stats.phpt1
-rw-r--r--ext/mysqli/tests/mysqli_info.phpt2
-rw-r--r--ext/mysqli/tests/mysqli_local_infile_default_off.phpt26
-rw-r--r--ext/mysqli/tests/mysqli_local_infile_set_on.phpt28
-rw-r--r--ext/mysqli/tests/mysqli_real_connect.phpt2
-rw-r--r--ext/mysqli/tests/mysqli_real_connect_pconn.phpt1
-rw-r--r--ext/mysqlnd/mysqlnd_connection.c3
-rw-r--r--ext/pdo_mysql/mysql_driver.c15
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt5
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt26
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt26
18 files changed, 149 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index fa5200ce84..a4dd406354 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,11 @@ PHP NEWS
. Fixed bug #77552 (Unintialized php_stream_statbuf in stat functions).
(John Stevenson)
+- MySQL
+ . Disabled LOCAL INFILE by default, can be enabled using php.ini directive
+ mysqli.allow_local_infile for mysqli, or PDO::MYSQL_ATTR_LOCAL_INFILE
+ attribute for pdo_mysql. (Darek Slusarczyk)
+
07 Feb 2019, PHP 7.2.15
- Core:
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 2d3b08bcb5..9e9f45fef9 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -524,7 +524,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("mysqli.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysqli_globals, mysqli_globals)
#endif
STD_PHP_INI_BOOLEAN("mysqli.reconnect", "0", PHP_INI_SYSTEM, OnUpdateLong, reconnect, zend_mysqli_globals, mysqli_globals)
- STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysqli_globals, mysqli_globals)
+ STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile", "0", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysqli_globals, mysqli_globals)
PHP_INI_END()
/* }}} */
@@ -549,7 +549,7 @@ static PHP_GINIT_FUNCTION(mysqli)
mysqli_globals->reconnect = 0;
mysqli_globals->report_mode = 0;
mysqli_globals->report_ht = 0;
- mysqli_globals->allow_local_infile = 1;
+ mysqli_globals->allow_local_infile = 0;
#ifdef HAVE_EMBEDDED_MYSQLI
mysqli_globals->embedded = 1;
#else
diff --git a/ext/mysqli/tests/061.phpt b/ext/mysqli/tests/061.phpt
index a6a0c4f205..12efe39c3f 100644
--- a/ext/mysqli/tests/061.phpt
+++ b/ext/mysqli/tests/061.phpt
@@ -17,6 +17,8 @@ if ($msg = check_local_infile_support($link, $engine))
mysqli_close($link);
?>
+--INI--
+mysqli.allow_local_infile=1
--FILE--
<?php
require_once("connect.inc");
diff --git a/ext/mysqli/tests/bug36745.phpt b/ext/mysqli/tests/bug36745.phpt
index 5e203e14eb..7a630afdc5 100644
--- a/ext/mysqli/tests/bug36745.phpt
+++ b/ext/mysqli/tests/bug36745.phpt
@@ -5,6 +5,8 @@ Bug #36745 (LOAD DATA LOCAL INFILE doesn't return correct error message)
require_once('skipif.inc');
require_once('skipifconnectfailure.inc');
?>
+--INI--
+mysqli.allow_local_infile=1
--FILE--
<?php
require_once("connect.inc");
diff --git a/ext/mysqli/tests/bug53503.phpt b/ext/mysqli/tests/bug53503.phpt
index bb8d00109f..fea62fde79 100644
--- a/ext/mysqli/tests/bug53503.phpt
+++ b/ext/mysqli/tests/bug53503.phpt
@@ -15,6 +15,8 @@ if ($msg = check_local_infile_support($link, $engine))
mysqli_close($link);
?>
+--INI--
+mysqli.allow_local_infile=1
--FILE--
<?php
require_once("connect.inc");
diff --git a/ext/mysqli/tests/bug68077.phpt b/ext/mysqli/tests/bug68077.phpt
index 0652e68c9b..174599ab48 100644
--- a/ext/mysqli/tests/bug68077.phpt
+++ b/ext/mysqli/tests/bug68077.phpt
@@ -17,6 +17,9 @@ if ($msg = check_local_infile_support($link, $engine))
mysqli_close($link);
?>
--INI--
+mysqli.allow_local_infile=1
+mysqli.allow_persistent=1
+mysqli.max_persistent=1
open_basedir=
--FILE--
<?php
diff --git a/ext/mysqli/tests/mysqli_constants.phpt b/ext/mysqli/tests/mysqli_constants.phpt
index 42113aef2b..64bd3a319b 100644
--- a/ext/mysqli/tests/mysqli_constants.phpt
+++ b/ext/mysqli/tests/mysqli_constants.phpt
@@ -6,6 +6,8 @@ require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
?>
+--INI--
+mysqli.allow_local_infile=1
--FILE--
<?php
require("connect.inc");
diff --git a/ext/mysqli/tests/mysqli_get_client_stats.phpt b/ext/mysqli/tests/mysqli_get_client_stats.phpt
index 29f8b430de..07ef78f296 100644
--- a/ext/mysqli/tests/mysqli_get_client_stats.phpt
+++ b/ext/mysqli/tests/mysqli_get_client_stats.phpt
@@ -12,6 +12,7 @@ if (!function_exists('mysqli_get_client_stats')) {
--INI--
mysqlnd.collect_statistics=1
mysqlnd.collect_memory_statistics=1
+mysqli.allow_local_infile=1
--FILE--
<?php
/*
diff --git a/ext/mysqli/tests/mysqli_info.phpt b/ext/mysqli/tests/mysqli_info.phpt
index d60ffd9fbe..9326a9c52a 100644
--- a/ext/mysqli/tests/mysqli_info.phpt
+++ b/ext/mysqli/tests/mysqli_info.phpt
@@ -6,6 +6,8 @@ require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
?>
+--INI--
+mysqli.allow_local_infile=1
--FILE--
<?php
require_once("connect.inc");
diff --git a/ext/mysqli/tests/mysqli_local_infile_default_off.phpt b/ext/mysqli/tests/mysqli_local_infile_default_off.phpt
new file mode 100644
index 0000000000..c2e8aa2dc8
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_local_infile_default_off.phpt
@@ -0,0 +1,26 @@
+--TEST--
+ensure default for local infile is off
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require_once("connect.inc");
+
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$res = mysqli_query($link, 'SHOW VARIABLES LIKE "local_infile"');
+$row = mysqli_fetch_assoc($res);
+echo "server: ", $row['Value'], "\n";
+mysqli_free_result($res);
+mysqli_close($link);
+
+echo "connector: ", ini_get("mysqli.allow_local_infile"), "\n";
+
+print "done!\n";
+?>
+--EXPECTF--
+server: %s
+connector: 0
+done!
diff --git a/ext/mysqli/tests/mysqli_local_infile_set_on.phpt b/ext/mysqli/tests/mysqli_local_infile_set_on.phpt
new file mode 100644
index 0000000000..172d6dcb9b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_local_infile_set_on.phpt
@@ -0,0 +1,28 @@
+--TEST--
+enable local infile
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+require_once("connect.inc");
+
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$res = mysqli_query($link, 'SHOW VARIABLES LIKE "local_infile"');
+$row = mysqli_fetch_assoc($res);
+echo "server: ", $row['Value'], "\n";
+mysqli_free_result($res);
+mysqli_close($link);
+
+echo "connector: ", ini_get("mysqli.allow_local_infile"), "\n";
+
+print "done!\n";
+?>
+--EXPECTF--
+server: %s
+connector: 1
+done!
diff --git a/ext/mysqli/tests/mysqli_real_connect.phpt b/ext/mysqli/tests/mysqli_real_connect.phpt
index a678399838..f68b51947b 100644
--- a/ext/mysqli/tests/mysqli_real_connect.phpt
+++ b/ext/mysqli/tests/mysqli_real_connect.phpt
@@ -6,6 +6,8 @@ require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
?>
+--INI--
+mysqli.allow_local_infile=1
--FILE--
<?php
include("connect.inc");
diff --git a/ext/mysqli/tests/mysqli_real_connect_pconn.phpt b/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
index 4cc18198c6..0d1c4985f2 100644
--- a/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
+++ b/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
@@ -10,6 +10,7 @@ if (!$IS_MYSQLND)
die("skip mysqlnd only test");
?>
--INI--
+mysqli.allow_local_infile=1
mysqli.allow_persistent=1
mysqli.max_persistent=10
--FILE--
diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c
index ea3d1cb0b7..dc42a16b6d 100644
--- a/ext/mysqlnd/mysqlnd_connection.c
+++ b/ext/mysqlnd/mysqlnd_connection.c
@@ -489,7 +489,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA *
MYSQLND_VIO * vio = conn->vio;
DBG_ENTER("mysqlnd_conn_data::get_updated_connect_flags");
- /* we allow load data local infile by default */
+ /* allow CLIENT_LOCAL_FILES capability, although extensions basing on mysqlnd
+ shouldn't allow 'load data local infile' by default due to security issues */
mysql_flags |= MYSQLND_CAPABILITIES;
mysql_flags |= conn->options->flags; /* use the flags from set_client_option() */
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c
index 07aaa6f6c1..c0708ceb12 100644
--- a/ext/pdo_mysql/mysql_driver.c
+++ b/ext/pdo_mysql/mysql_driver.c
@@ -502,6 +502,12 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_
case PDO_MYSQL_ATTR_MAX_BUFFER_SIZE:
ZVAL_LONG(return_value, H->max_buffer_size);
break;
+#else
+ case PDO_MYSQL_ATTR_LOCAL_INFILE:
+ ZVAL_BOOL(
+ return_value,
+ (H->server->data->options->flags & CLIENT_LOCAL_FILES) == CLIENT_LOCAL_FILES);
+ break;
#endif
default:
@@ -786,6 +792,15 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
}
}
#endif
+ } else {
+#if defined(MYSQL_OPT_LOCAL_INFILE) || defined(PDO_USE_MYSQLND)
+ // in case there are no driver options disable 'local infile' explicitly
+ zend_long local_infile = 0;
+ if (mysql_options(H->server, MYSQL_OPT_LOCAL_INFILE, (const char *)&local_infile)) {
+ pdo_mysql_error(dbh);
+ goto cleanup;
+ }
+#endif
}
#ifdef PDO_MYSQL_HAS_CHARSET
diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt
index 62051d7ae2..08cd8eb942 100644
--- a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt
@@ -19,7 +19,7 @@ MySQLPDOTest::skip();
try {
$db = new PDO($dsn, $user, $pass, array($option => $value));
if (!is_object($db) || ($value !== ($tmp = @$db->getAttribute($option))))
- printf("[%03d] Execting '%s'/%s got '%s'/%s' for options '%s'\n",
+ printf("[%03d] Expecting '%s'/%s got '%s'/%s' for options '%s'\n",
$offset,
$value, gettype($value),
$tmp, gettype($tmp),
@@ -172,8 +172,7 @@ MySQLPDOTest::skip();
[016] PDO::MYSQL_ATTR_DIRECT_QUERY should be on
[017] PDO::ATTR_EMULATE_PREPARES should be off
[018] PDO::MYSQL_ATTR_DIRECT_QUERY should be off
-[021] Execting '1'/boolean got ''/boolean' for options 'PDO::MYSQL_ATTR_LOCAL_INFILE'
-[023] Execting 'SET @a=1'/string got ''/boolean' for options 'PDO::MYSQL_ATTR_INIT_COMMAND'
+[023] Expecting 'SET @a=1'/string got ''/boolean' for options 'PDO::MYSQL_ATTR_INIT_COMMAND'
[024] SQLSTATE[42000] [1065] Query was empty
[025] SQLSTATE[42S02] [1146] Table '%s.nonexistent' doesn't exist
done!
diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt
new file mode 100644
index 0000000000..5a0b5f67e0
--- /dev/null
+++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt
@@ -0,0 +1,26 @@
+--TEST--
+ensure default for local infile is off
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+if (!MYSQLPDOTest::isPDOMySQLnd())
+ die("skip mysqlnd only test");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+
+$dsn = MySQLPDOTest::getDSN();
+$user = PDO_MYSQL_TEST_USER;
+$pass = PDO_MYSQL_TEST_PASS;
+
+$db = new PDO($dsn, $user, $pass);
+echo var_export($db->getAttribute(PDO::MYSQL_ATTR_LOCAL_INFILE)), "\n";
+echo "done!\n";
+?>
+--EXPECTF--
+false
+done!
diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt
new file mode 100644
index 0000000000..4394bc0576
--- /dev/null
+++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt
@@ -0,0 +1,26 @@
+--TEST--
+enable local infile
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+if (!MYSQLPDOTest::isPDOMySQLnd())
+ die("skip mysqlnd only test");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+
+$dsn = MySQLPDOTest::getDSN();
+$user = PDO_MYSQL_TEST_USER;
+$pass = PDO_MYSQL_TEST_PASS;
+
+$db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_LOCAL_INFILE => true));
+echo var_export($db->getAttribute(PDO::MYSQL_ATTR_LOCAL_INFILE)), "\n";
+echo "done!\n";
+?>
+--EXPECTF--
+true
+done!