summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavey Shafik <me@daveyshafik.com>2015-12-07 01:04:46 -0500
committerDavey Shafik <me@daveyshafik.com>2015-12-07 01:04:46 -0500
commit0a6610cdb671a4579f90388d6489db72c7b57d9c (patch)
tree4b7ab00dedefaf33647ad9e4adff193fb5533379
parent5f20827302d32a08cfcafe3b0cc9be0dc0a1c14c (diff)
downloadphp7-mysql-shim-0a6610cdb671a4579f90388d6489db72c7b57d9c.zip
php7-mysql-shim-0a6610cdb671a4579f90388d6489db72c7b57d9c.tar.gz
php7-mysql-shim-0a6610cdb671a4579f90388d6489db72c7b57d9c.tar.bz2
More tests, more fixes
- Reimplement original `mysql_escape_string()` based on C-code as close as possible - For some reason `mysql_fetch_object()` has a different error than all the other `mysql_fetch_*()` functions when passed an invalid result. ಠ_ಠ
-rw-r--r--lib/mysql.php127
-rw-r--r--tests/MySqlShimTest.php131
2 files changed, 246 insertions, 12 deletions
diff --git a/lib/mysql.php b/lib/mysql.php
index af92240..03ebdce 100644
--- a/lib/mysql.php
+++ b/lib/mysql.php
@@ -166,7 +166,9 @@ namespace {
}
trigger_error("mysql_list_fields(): Unable to save MySQL query result", E_USER_WARNING);
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
function mysql_list_processes(\mysqli $link = null)
@@ -194,8 +196,14 @@ namespace {
return mysqli_insert_id(\Dshafik\MySQL::getConnection($link));
}
- function mysql_result(\mysqli_result $result, $row, $field = 0)
+ function mysql_result($result, $row, $field = 0)
{
+ if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
if (!mysqli_data_seek($result, $row)) {
trigger_error(
sprintf(
@@ -244,8 +252,14 @@ namespace {
// @codeCoverageIgnoreEnd
}
- function mysql_num_rows(\mysqli_result $result)
+ function mysql_num_rows($result)
{
+ if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
$previous = error_reporting(0);
$rows = mysqli_num_rows($result);
error_reporting($previous);
@@ -256,23 +270,29 @@ namespace {
function mysql_num_fields($result)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_num_fields($result);
}
- function mysql_fetch_row($result) /* : array|null */
+ function mysql_fetch_row($result)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_fetch_row($result);
}
- function mysql_fetch_array($result) /* : array|null */
+ function mysql_fetch_array($result)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_fetch_array($result);
}
@@ -280,7 +300,9 @@ namespace {
function mysql_fetch_assoc($result) /* : array|null */
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_fetch_assoc($result);
}
@@ -288,7 +310,9 @@ namespace {
function mysql_fetch_object($result, $class = null, array $params = []) /* : object|null */
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
if ($class == null) {
@@ -301,7 +325,9 @@ namespace {
function mysql_data_seek($result, $offset)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_data_seek($result, $offset);
}
@@ -309,7 +335,9 @@ namespace {
function mysql_fetch_lengths($result) /* : array|*/
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_fetch_lengths($result);
}
@@ -317,7 +345,9 @@ namespace {
function mysql_fetch_field($result) /* : object|*/
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_fetch_field($result);
}
@@ -325,7 +355,9 @@ namespace {
function mysql_field_seek($result, $field)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_field_seek($result, $field);
}
@@ -333,7 +365,9 @@ namespace {
function mysql_free_result($result)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return mysqli_free_result($result);
}
@@ -341,7 +375,9 @@ namespace {
function mysql_field_name($result, $field)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'name');
}
@@ -349,7 +385,9 @@ namespace {
function mysql_field_table($result, $field)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'table');
}
@@ -357,7 +395,9 @@ namespace {
function mysql_field_len($result, $field)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'len');
}
@@ -365,7 +405,9 @@ namespace {
function mysql_field_type($result, $field)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'type');
}
@@ -373,13 +415,26 @@ namespace {
function mysql_field_flags($result, $field)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'flags');
}
function mysql_escape_string($unescapedString)
{
+ if (\Dshafik\MySQL::$last_connection == null) {
+ trigger_error(
+ sprintf(
+ "%s() is insecure; use mysql_real_escape_string() instead!",
+ __FUNCTION__
+ ),
+ E_USER_NOTICE
+ );
+
+ return \Dshafik\MySQL::escapeString($unescapedString);
+ }
return mysql_real_escape_string($unescapedString, null);
}
@@ -438,20 +493,28 @@ namespace {
return mysqli_set_charset(\Dshafik\MySQL::getConnection($link), $charset);
}
- function mysql_db_name($result)
+ function mysql_db_name($result, $row)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
- return mysqli_fetch_row($result)['Database'];
+
+ // Alias as per http://lxr.php.net/xref/PHP_5_6/ext/mysql/php_mysql.c#319
+ return mysql_result($result, $row, 'Database');
}
- function mysql_table_name($result)
+ function mysql_table_name($result, $row)
{
if (\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
+ // @codeCoverageIgnoreStart
return false;
+ // @codeCoverageIgnoreEnd
}
- return mysqli_fetch_row($result)['Table'];
+
+ // Alias as per http://lxr.php.net/xref/PHP_5_6/ext/mysql/php_mysql.c#321
+ return mysql_result($result, $row, 'Table');
}
/* Aliases */
@@ -595,12 +658,52 @@ namespace Dshafik {
public static function checkValidResult($result, $function)
{
if (!($result instanceof \mysqli_result)) {
- trigger_error(
- $function . "() expects parameter 1 to be resource, " . gettype($result) . " given",
- E_USER_WARNING
- );
+ if ($function != "mysql_fetch_object") {
+ trigger_error(
+ $function . "() expects parameter 1 to be resource, " . strtolower(gettype($result)) . " given",
+ E_USER_WARNING
+ );
+ }
+
+ if ($function == "mysql_fetch_object") {
+ trigger_error(
+ $function . "(): supplied argument is not a valid MySQL result resource",
+ E_USER_WARNING
+ );
+ }
return false;
}
+
+ }
+
+ public static function escapeString($unescapedString)
+ {
+ $escapedString = "";
+ for ($i = 0; $i < strlen($unescapedString); $i++) {
+ switch ($unescapedString{$i}) {
+ case "\0":
+ $esc = 0;
+ break;
+ case "\n":
+ $esc = "n";
+ break;
+ case "\r":
+ $esc = "r";
+ break;
+ case '\\':
+ case '\'':
+ case '"':
+ $esc = $unescapedString{$i};
+ break;
+ case "\032":
+ $esc = 'Z';
+ break;
+ }
+ $escapedString .= "\\$esc";
+
+ }
+
+ return $escapedString;
}
protected static function getFieldFlags($what)
diff --git a/tests/MySqlShimTest.php b/tests/MySqlShimTest.php
index 19fa72e..8a2e063 100644
--- a/tests/MySqlShimTest.php
+++ b/tests/MySqlShimTest.php
@@ -450,6 +450,21 @@ class MySqlShimTest extends \PHPUnit_Framework_TestCase
}
/**
+ * @dataProvider mysql_function_invalid_result_DataProvider
+ */
+ public function test_mysql_function_invalid_result($function, $error, $args)
+ {
+ try {
+ if ($args !== []) {
+ $function(null, ...$args);
+ }
+ $function(null);
+ } catch (\PHPUnit_Framework_Error_Warning $e) {
+ $this->assertEquals($error, $e->getMessage());
+ }
+ }
+
+ /**
* @dataProvider mysql_fetch_DataProvider
*/
public function test_mysql_fetch($function, $results)
@@ -602,6 +617,21 @@ class MySqlShimTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(1064, mysql_errno());
}
+ public function test_mysql_escape_string()
+ {
+ $this->assertEquals('\\\'\0\Z\r\n\"\\\\', @mysql_escape_string("'\0\032\r\n\"\\"));
+ }
+
+ /**
+ * @requires PHP 7.0.0
+ * @expectedException \PHPUnit_Framework_Error_Notice
+ * @expectedExceptionMessage mysql_escape_string() is insecure; use mysql_real_escape_string() instead!
+ */
+ public function test_mysql_escape_string_notice()
+ {
+ mysql_escape_string("'\0\032\r\n\"\\");
+ }
+
public function tearDown()
{
@mysql_close();
@@ -744,6 +774,107 @@ class MySqlShimTest extends \PHPUnit_Framework_TestCase
];
}
+ public function mysql_function_invalid_result_DataProvider()
+ {
+ return [
+ [
+ "function" => "mysql_result",
+ "message" => "mysql_result() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_num_rows",
+ "message" => "mysql_num_rows() expects parameter 1 to be resource, null given",
+ "args" => [],
+ ],
+ [
+ "function" => "mysql_num_fields",
+ "message" => "mysql_num_fields() expects parameter 1 to be resource, null given",
+ "args" => [],
+ ],
+ [
+ "function" => "mysql_fetch_row",
+ "message" => "mysql_fetch_row() expects parameter 1 to be resource, null given",
+ "args" => [],
+ ],
+ [
+ "function" => "mysql_fetch_array",
+ "message" => "mysql_fetch_array() expects parameter 1 to be resource, null given",
+ "args" => [],
+ ],
+ [
+ "function" => "mysql_fetch_assoc",
+ "message" => "mysql_fetch_assoc() expects parameter 1 to be resource, null given",
+ "args" => [],
+ ],
+ [
+ "function" => "mysql_fetch_object",
+ "message" => "mysql_fetch_object(): supplied argument is not a valid MySQL result resource",
+ "args" => ["StdClass"]
+ ],
+ [
+ "function" => "mysql_data_seek",
+ "message" => "mysql_data_seek() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_fetch_lengths",
+ "message" => "mysql_fetch_lengths() expects parameter 1 to be resource, null given",
+ "args" => []
+ ],
+ [
+ "function" => "mysql_fetch_field",
+ "message" => "mysql_fetch_field() expects parameter 1 to be resource, null given",
+ "args" => []
+ ],
+ [
+ "function" => "mysql_field_seek",
+ "message" => "mysql_field_seek() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_free_result",
+ "message" => "mysql_free_result() expects parameter 1 to be resource, null given",
+ "args" => []
+ ],
+ [
+ "function" => "mysql_field_name",
+ "message" => "mysql_field_name() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_field_table",
+ "message" => "mysql_field_table() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_field_len",
+ "message" => "mysql_field_len() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_field_type",
+ "message" => "mysql_field_type() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_field_flags",
+ "message" => "mysql_field_flags() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_db_name",
+ "message" => "mysql_db_name() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ [
+ "function" => "mysql_table_name",
+ "message" => "mysql_table_name() expects parameter 1 to be resource, null given",
+ "args" => [0]
+ ],
+ ];
+ }
+
/**
* @param $result
*/