8000 Better fix for bug #67072 with more BC provisions · php/php-src@2c88ae5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2c88ae5

Browse files
smalyshevJulien Pauli
authored andcommitted
Better fix for bug #67072 with more BC provisions
1 parent e72b732 commit 2c88ae5

File tree

3 files changed

+120
-34
lines changed

3 files changed

+120
-34
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
--TEST--
2+
Bug #67072 Echoing unserialized "SplFileObject" crash - BC break fixes
3+
--FILE--
4+
<?php
5+
class MySplFileObject extends SplFileObject {}
6+
class MyArrayObject extends ArrayObject{ var $a = 1; }
7+
echo unserialize('O:15:"MySplFileObject":1:{s:9:"*filename";s:15:"/home/flag/flag";}');
8+
9+
function testClass($className)
10+
{
11+
// simulate phpunit
12+
$object = unserialize(sprintf('O:%d:"%s":0:{}', strlen($className), $className));
13+
return $object;
14+
}
15+
16+
class MyClass {}
17+
class MyClassSer implements Serializable {
18+
function serialize() { return "";}
19+
function unserialize($data) { }
20+
}
21+
class MyClassSer2 extends MyClassSer {
22+
}
23+
24+
$classes = array('stdClass', 'MyClass', 'MyClassSer', 'MyClassSer2', 'SplFileObject', 'MySplFileObject',
25+
'SplObjectStorage', 'FooBar', 'Closure', 'ArrayObject', 'MyArrayObject',
26+
'Directory'
27+
);
28+
foreach($classes as $cl) {
29+
var_dump(testClass($cl));
30+
}
31+
32+
?>
33+
===DONE==
34+
--EXPECTF--
35+
Warning: Erroneous data format for unserializing 'MySplFileObject' in %s on line 4
36+
37+
Notice: unserialize(): Error at offset 26 of 66 bytes in %s on line 4
38+
object(stdClass)#%d (0) {
39+
}
40+
object(MyClass)#%d (0) {
41+
}
42+
object(MyClassSer)#%d (0) {
43+
}
44+
object(MyClassSer2)#%d (0) {
45+
}
46+
47+
Warning: Erroneous data format for unserializing 'SplFileObject' in %s on line 9
48+
49+
Notice: unserialize(): Error at offset 24 of 25 bytes in %s on line 9
50+
bool(false)
51+
52+
Warning: Erroneous data format for unserializing 'MySplFileObject' in %s on line 9
53+
54+
Notice: unserialize(): Error at offset 26 of 27 bytes in %s on line 9
55+
bool(false)
56+
object(SplObjectStorage)#%d (1) {
57+
["storage":"SplObjectStorage":private]=>
58+
array(0) {
59+
}
60+
}
61+
object(__PHP_Incomplete_Class)#%d (1) {
62+
["__PHP_Incomplete_Class_Name"]=>
63+
string(6) "FooBar"
64+
}
65+
66+
Warning: Erroneous data format for unserializing 'Closure' in %s on line 9
67+
68+
Notice: unserialize(): Error at offset 17 of 18 bytes in %s on line 9
69+
bool(false)
70+
object(ArrayObject)#%d (1) {
71+
["storage":"ArrayObject":private]=>
72+
array(0) {
73+
}
74+
}
75+
object(MyArrayObject)#1 (2) {
76+
["a"]=>
77+
int(1)
78+
["storage":"ArrayObject":private]=>
79+
array(0) {
80+
}
81+
}
82+
object(Directory)#1 (0) {
83+
}
84+
===DONE==

ext/standard/var_unserializer.c

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Generated by re2c 0.13.5 on Tue Jun 3 10:23:35 2014 */
1+
/* Generated by re2c 0.13.5 on Sat Jun 21 21:27:56 2014 */
22
#line 1 "ext/standard/var_unserializer.re"
33
/*
44
+----------------------------------------------------------------------+
@@ -23,6 +23,7 @@
2323
#include "php.h"
2424
#include "ext/standard/php_var.h"
2525
#include "php_incomplete_class.h"
26+
#include "Zend/zend_interfaces.h"
2627

2728
/* {{{ reference-handling for unserializer: var_* */
2829
#define VAR_ENTRIES_MAX 1024
@@ -226,7 +227,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
226227
#define YYMARKER marker
227228

228229

229-
#line 234 "ext/standard/var_unserializer.re"
230+
#line 235 "ext/standard/var_unserializer.re"
230231

231232

232233

@@ -400,7 +401,7 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
400401
Serializable interface have eventually an inconsistent behavior at this place when
401402
unserialized from a manipulated string. Additionaly the interal classes can possibly
402403
crash PHP so they're still disabled here. */
403-
if (ce->serialize == NULL || ZEND_INTERNAL_CLASS != ce->type) {
404+
if (ce->serialize == NULL || ce->unserialize == zend_user_unserialize || (ZEND_INTERNAL_CLASS != ce->type && ce->create_object == NULL)) {
404405
object_init_ex(*rval, ce);
405406
} else {
406407
/* If this class implements Serializable, it should not land here but in object_custom(). The passed string
@@ -473,7 +474,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
473474

474475

475476

476-
#line 477 "ext/standard/var_unserializer.c"
477+
#line 478 "ext/standard/var_unserializer.c"
477478
{
478479
YYCTYPE yych;
479480
static const unsigned char yybm[] = {
@@ -533,9 +534,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
533534
yych = *(YYMARKER = ++YYCURSOR);
534535
if (yych == ':') goto yy95;
535536
yy3:
536-
#line 828 "ext/standard/var_unserializer.re"
537+
#line 829 "ext/standard/var_unserializer.re"
537538
{ return 0; }
538-
#line 539 "ext/standard/var_unserializer.c"
539+
#line 540 "ext/standard/var_unserializer.c"
539540
yy4:
540541
yych = *(YYMARKER = ++YYCURSOR);
541542
if (yych == ':') goto yy89;
@@ -578,13 +579,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
578579
goto yy3;
579580
yy14:
580581
++YYCURSOR;
581-
#line 822 "ext/standard/var_unserializer.re"
582+
#line 823 "ext/standard/var_unserializer.re"
582583
{
583584
/* this is the case where we have less data than planned */
584585
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
585586
return 0; /* not sure if it should be 0 or 1 here? */
586587
}
587-
#line 588 "ext/standard/var_unserializer.c"
588+
#line 589 "ext/standard/var_unserializer.c"
588589
yy16:
589590
yych = *++YYCURSOR;
590591
goto yy3;
@@ -614,7 +615,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
614615
yych = *++YYCURSOR;
615616
if (yych != '"') goto yy18;
616617
++YYCURSOR;
617-
#line 676 "ext/standard/var_unserializer.re"
618+
#line 677 "ext/standard/var_unserializer.re"
618619
{
619620
size_t len, len2, len3, maxlen;
620621
long elements;
@@ -760,7 +761,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
760761

761762
return object_common2(UNSERIALIZE_PASSTHRU, elements);
762763
}
763-
#line 764 "ext/standard/var_unserializer.c"
764+
#line 765 "ext/standard/var_unserializer.c"
764765
yy25:
765766
yych = *++YYCURSOR;
766767
if (yych <= ',') {
@@ -785,15 +786,15 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
785786
yych = *++YYCURSOR;
786787
if (yych != '"') goto yy18;
787788
++YYCURSOR;
788-
#line 668 "ext/standard/var_unserializer.re"
789+
#line 669 "ext/standard/var_unserializer.re"
789790
{
790791

791792
INIT_PZVAL(*rval);
792793

793794
return object_common2(UNSERIALIZE_PASSTHRU,
794795
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
795796
}
796-
#line 797 "ext/standard/var_unserializer.c"
797+
#line 798 "ext/standard/var_unserializer.c"
797798
yy32:
798799
yych = *++YYCURSOR;
799800
if (yych == '+') goto yy33;
@@ -814,7 +815,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
814815
yych = *++YYCURSOR;
815816
if (yych != '{') goto yy18;
816817
++YYCURSOR;
817-
#line 648 "ext/standard/var_unserializer.re"
818+
#line 649 "ext/standard/var_unserializer.re"
818819
{
819820
long elements = parse_iv(start + 2);
820821
/* use iv() not uiv() in order to check data range */
@@ -834,7 +835,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
834835

835836
return finish_nested_data(UNSERIALIZE_PASSTHRU);
836837
}
837-
#line 838 "ext/standard/var_unserializer.c"
838+
#line 839 "ext/standard/var_unserializer.c"
838839
yy39:
839840
yych = *++YYCURSOR;
840841
if (yych == '+') goto yy40;
@@ -855,7 +856,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
855856
yych = *++YYCURSOR;
856857
if (yych != '"') goto yy18;
857858
++YYCURSOR;
858-
#line 619 "ext/standard/var_unserializer.re"
859+
#line 620 "ext/standard/var_unserializer.re"
859860
{
860861
size_t len, maxlen;
861862
char *str;
@@ -884,7 +885,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
884885
ZVAL_STRINGL(*rval, str, len, 0);
885886
return 1;
886887
}
887-
#line 888 "ext/standard/var_unserializer.c"
888+
#line 889 "ext/standard/var_unserializer.c"
888889
yy46:
889890
yych = *++YYCURSOR;
890891
if (yych == '+') goto yy47;
@@ -905,7 +906,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
905906
yych = *++YYCURSOR;
906907
if (yych != '"') goto yy18;
907908
++YYCURSOR;
908-
#line 591 "ext/standard/var_unserializer.re"
909+
#line 592 "ext/standard/var_unserializer.re"
909910
{
910911
size_t len, maxlen;
911912
char *str;
@@ -933,7 +934,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
933934
ZVAL_STRINGL(*rval, str, len, 1);
934935
return 1;
935936
}
936-
#line 937 "ext/standard/var_unserializer.c"
937+
#line 938 "ext/standard/var_unserializer.c"
937938
yy53:
938939
yych = *++YYCURSOR;
939940
if (yych <= '/') {
@@ -1021,7 +1022,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10211022
}
10221023
yy63:
10231024
++YYCURSOR;
1024-
#line 581 "ext/standard/var_unserializer.re"
1025+
#line 582 "ext/standard/var_unserializer.re"
10251026
{
10261027
#if SIZEOF_LONG == 4
10271028
use_double:
@@ -1031,7 +1032,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10311032
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
10321033
return 1;
10331034
}
1034-
#line 1035 "ext/standard/var_unserializer.c"
1035+
#line 1036 "ext/standard/var_unserializer.c"
10351036
yy65:
10361037
yych = *++YYCURSOR;
10371038
if (yych <= ',') {
@@ -1090,7 +1091,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10901091
yych = *++YYCURSOR;
10911092
if (yych != ';') goto yy18;
10921093
++YYCURSOR;
1093-
#line 566 "ext/standard/var_unserializer.re"
1094+
#line 567 "ext/standard/var_unserializer.re"
10941095
{
10951096
*p = YYCURSOR;
10961097
INIT_PZVAL(*rval);
@@ -1105,7 +1106,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11051106

11061107
return 1;
11071108
}
1108-
#line 1109 "ext/standard/var_unserializer.c"
1109+
#line 1110 "ext/standard/var_unserializer.c"
11091110
yy76:
11101111
yych = *++YYCURSOR;
11111112
if (yych == 'N') goto yy73;
@@ -1132,7 +1133,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11321133
if (yych <= '9') goto yy79;
11331134
if (yych != ';') goto yy18;
11341135
++YYCURSOR;
1135-
#line 539 "ext/standard/var_unserializer.re"
1136+
#line 540 "ext/standard/var_unserializer.re"
11361137
{
11371138
#if SIZEOF_LONG == 4
11381139
int digits = YYCURSOR - start - 3;
@@ -1159,32 +1160,32 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11591160
ZVAL_LONG(*rval, parse_iv(start + 2));
11601161
return 1;
11611162
}
1162-
#line 1163 "ext/standard/var_unserializer.c"
1163+
#line 1164 "ext/standard/var_unserializer.c"
11631164
yy83:
11641165
yych = *++YYCURSOR;
11651166
if (yych <= '/') goto yy18;
11661167
if (yych >= '2') goto yy18;
11671168
yych = *++YYCURSOR;
11681169
if (yych != ';') goto yy18;
11691170
++YYCURSOR;
1170-
#line 532 "ext/standard/var_unserializer.re"
1171+
#line 533 "ext/standard/var_unserializer.re"
11711172
{
11721173
*p = YYCURSOR;
11731174
INIT_PZVAL(*rval);
11741175
ZVAL_BOOL(*rval, parse_iv(start + 2));
11751176
return 1;
11761177
}
1177-
#line 1178 "ext/standard/var_unserializer.c"
1178+
#line 1179 "ext/standard/var_unserializer.c"
11781179
yy87:
11791180
++YYCURSOR;
1180-
#line 525 "ext/standard/var_unserializer.re"
1181+
#line 526 "ext/standard/var_unserializer.re"
11811182
{
11821183
*p = YYCURSOR;
11831184
INIT_PZVAL(*rval);
11841185
ZVAL_NULL(*rval);
11851186
return 1;
11861187
}
1187-
#line 1188 "ext/standard/var_unserializer.c"
1188+
#line 1189 "ext/standard/var_unserializer.c"
11881189
yy89:
11891190
yych = *++YYCURSOR;
11901191
if (yych <= ',') {
@@ -1207,7 +1208,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12071208
if (yych <= '9') goto yy91;
12081209
if (yych != ';') goto yy18;
12091210
++YYCURSOR;
1210-
#line 502 "ext/standard/var_unserializer.re"
1211+
#line 503 "ext/standard/var_unserializer.re"
12111212
{
12121213
long id;
12131214

@@ -1230,7 +1231,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12301231

12311232
return 1;
12321233
}
1233-
#line 1234 "ext/standard/var_unserializer.c"
1234+
#line 1235 "ext/standard/var_unserializer.c"
12341235
yy95:
12351236
yych = *++YYCURSOR;
12361237
if (yych <= ',') {
@@ -1253,7 +1254,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12531254
if (yych <= '9') goto yy97;
12541255
if (yych != ';') goto yy18;
12551256
++YYCURSOR;
1256-
#line 481 "ext/standard/var_unserializer.re"
1257+
#line 482 "ext/standard/var_unserializer.re"
12571258
{
12581259
long id;
12591260

@@ -1274,9 +1275,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12741275

12751276
return 1;
12761277
}
1277-
#line 1278 "ext/standard/var_unserializer.c"
1278+
#line 1279 "ext/standard/var_unserializer.c"
12781279
}
1279-
#line 830 "ext/standard/var_unserializer.re"
1280+
#line 831 "ext/standard/var_unserializer.re"
12801281

12811282

12821283
return 0;

ext/standard/var_unserializer.re

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "php.h"
2222
#include "ext/standard/php_var.h"
2323
#include "php_incomplete_class.h"
24+
#include "Zend/zend_interfaces.h"
2425

2526
/* {{{ reference-handling for unserializer: var_* */
2627
#define VAR_ENTRIES_MAX 1024
@@ -404,7 +405,7 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
404405
Serializable interface have eventually an inconsistent behavior at this place when
405406
unserialized from a manipulated string. Additionaly the interal classes can possibly
406407
crash PHP so they're still disabled here. */
407-
if (ce->serialize == NULL || ZEND_INTERNAL_CLASS != ce->type) {
408+
if (ce->serialize == NULL || ce->unserialize == zend_user_unserialize || (ZEND_INTERNAL_CLASS != ce->type && ce->create_object == NULL)) {
408409
object_init_ex(*rval, ce);
409410
} else {
410411
/* If this class implements Serializable, it should not land here but in object_custom(). The passed string

0 commit comments

Comments
 (0)
0