From 8deb49f534073304fd501a96ef3fac7bda4c76ce Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Thu, 14 Jan 2016 16:11:44 -0500 Subject: [PATCH] API: Work around PHP bug 45959 Sigh, PHP. You allow for an array to have string "1" as a key (e.g. when casting from object to array), but then you do everything wrong when trying to deal with it. Bug: T123663 Change-Id: I49f09901a69aab39ca1519bbe9e41267bf9a1216 --- includes/api/ApiResult.php | 6 ++++- tests/phpunit/includes/api/ApiResultTest.php | 24 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php index bd5fe08cea..71af80cf97 100644 --- a/includes/api/ApiResult.php +++ b/includes/api/ApiResult.php @@ -364,9 +364,13 @@ class ApiResult implements ApiSerializable { } } if ( is_array( $value ) ) { + // Work around PHP bug 45959 by copying to a temporary + // (in this case, foreach gets $k === "1" but $tmp[$k] assigns as if $k === 1) + $tmp = array(); foreach ( $value as $k => $v ) { - $value[$k] = self::validateValue( $v ); + $tmp[$k] = self::validateValue( $v ); } + $value = $tmp; } elseif ( is_float( $value ) && !is_finite( $value ) ) { throw new InvalidArgumentException( "Cannot add non-finite floats to ApiResult" ); } elseif ( is_string( $value ) ) { diff --git a/tests/phpunit/includes/api/ApiResultTest.php b/tests/phpunit/includes/api/ApiResultTest.php index 9dbde3d93f..292d276b68 100644 --- a/tests/phpunit/includes/api/ApiResultTest.php +++ b/tests/phpunit/includes/api/ApiResultTest.php @@ -218,6 +218,17 @@ class ApiResultTest extends MediaWikiTestCase { 0 => "foo\xef\xbf\xbdbar", 1 => "\xc3\xa1", ), $arr ); + + $obj = new stdClass; + $obj->{'1'} = 'one'; + $arr = array(); + ApiResult::setValue( $arr, 'foo', $obj ); + $this->assertSame( array( + 'foo' => array( + 1 => 'one', + ApiResult::META_TYPE => 'assoc', + ) + ), $arr ); } /** @@ -509,6 +520,19 @@ class ApiResultTest extends MediaWikiTestCase { 1 => "\xc3\xa1", ApiResult::META_TYPE => 'assoc', ), $result->getResultData() ); + + $result = new ApiResult( 8388608 ); + $obj = new stdClass; + $obj->{'1'} = 'one'; + $arr = array(); + $result->addValue( $arr, 'foo', $obj ); + $this->assertSame( array( + 'foo' => array( + 1 => 'one', + ApiResult::META_TYPE => 'assoc', + ), + ApiResult::META_TYPE => 'assoc', + ), $result->getResultData() ); } /** -- 2.20.1