Skip to content

Commit 041610d

Browse files
author
cpriest
committed
Conflicts: Zend/zend_language_scanner.c Zend/zend_language_scanner_defs.h
2 parents d7e998f + 3067f54 commit 041610d

File tree

95 files changed

+5216
-3640
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+5216
-3640
lines changed

Makefile.frag

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ $(builddir)/zend_language_scanner.lo: $(srcdir)/zend_language_parser.h
77
$(builddir)/zend_ini_scanner.lo: $(srcdir)/zend_ini_parser.h
88

99
$(srcdir)/zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
10-
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l)
10+
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l)
1111

1212
$(srcdir)/zend_language_parser.h: $(srcdir)/zend_language_parser.c
1313
$(srcdir)/zend_language_parser.c: $(srcdir)/zend_language_parser.y
@@ -18,6 +18,6 @@ $(srcdir)/zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
1818
@$(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o $@
1919

2020
$(srcdir)/zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
21-
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
21+
@(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l)
2222

2323
$(builddir)/zend_indent.lo $(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(srcdir)/zend_language_parser.h

Makefile.global

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ test: all
102102
TEST_PHP_SRCDIR=$(top_srcdir) \
103103
CC="$(CC)" \
104104
$(PHP_EXECUTABLE) -n -c $(top_builddir)/tmp-php.ini $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -n -c $(top_builddir)/tmp-php.ini -d extension_dir=$(top_builddir)/modules/ $(PHP_TEST_SHARED_EXTENSIONS) $(TESTS); \
105+
TEST_RESULT_EXIT_CODE=$$?; \
105106
rm $(top_builddir)/tmp-php.ini; \
107+
exit $$TEST_RESULT_EXIT_CODE; \
106108
else \
107109
echo "ERROR: Cannot run tests without CLI sapi."; \
108110
fi

Zend/Makefile.am

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ zend_ini_scanner.lo: zend_ini_parser.h
3232
# Language parser/scanner rules
3333

3434
zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
35-
$(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt $(srcdir)/zend_language_scanner_defs.h -o$@ $(srcdir)/zend_language_scanner.l
35+
$(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt $(srcdir)/zend_language_scanner_defs.h -o$@ $(srcdir)/zend_language_scanner.l
3636

3737
zend_language_parser.h: zend_language_parser.c
3838
zend_language_parser.c: $(srcdir)/zend_language_parser.y
@@ -44,7 +44,7 @@ zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
4444
$(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o zend_ini_parser.c
4545

4646
zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
47-
$(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt $(srcdir)/zend_ini_scanner_defs.h -o$@ $(srcdir)/zend_ini_scanner.l
47+
$(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt $(srcdir)/zend_ini_scanner_defs.h -o$@ $(srcdir)/zend_ini_scanner.l
4848

4949
zend_ini_parser.h: zend_ini_parser.c
5050

Zend/tests/bug63635.phpt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
Bug #63635 (Segfault in gc_collect_cycles)
3+
--FILE--
4+
<?php
5+
class Node {
6+
public $parent = NULL;
7+
public $childs = array();
8+
9+
function __construct(Node $parent=NULL) {
10+
if ($parent) {
11+
$parent->childs[] = $this;
12+
}
13+
$this->childs[] = $this;
14+
}
15+
16+
function __destruct() {
17+
$this->childs = NULL;
18+
}
19+
}
20+
21+
define("MAX", 16);
22+
23+
for ($n = 0; $n < 20; $n++) {
24+
$top = new Node();
25+
for ($i=0 ; $i<MAX ; $i++) {
26+
$ci = new Node($top);
27+
for ($j=0 ; $j<MAX ; $j++) {
28+
$cj = new Node($ci);
29+
for ($k=0 ; $k<MAX ; $k++) {
30+
$ck = new Node($cj);
31+
}
32+
}
33+
}
34+
echo "$n\n";
35+
}
36+
echo "ok\n";
37+
--EXPECT--
38+
0
39+
1
40+
2
41+
3
42+
4
43+
5
44+
6
45+
7
46+
8
47+
9
48+
10
49+
11
50+
12
51+
13
52+
14
53+
15
54+
16
55+
17
56+
18
57+
19
58+
ok

Zend/tests/generators/bug63066.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Bug #63066 (Calling an undefined method in a generator results in a seg fault)
3+
--FILE--
4+
<?php
5+
function gen($o)
6+
{
7+
yield 'foo';
8+
$o->fatalError();
9+
}
10+
11+
foreach(gen(new stdClass()) as $value)
12+
echo $value, "\n";
13+
--EXPECTF--
14+
foo
15+
16+
Fatal error: Call to undefined method stdClass::fatalError() in %sbug63066.php on line 5

Zend/zend.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,11 +683,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
683683
#if HAVE_DTRACE
684684
/* build with dtrace support */
685685
zend_compile_file = dtrace_compile_file;
686-
zend_execute = dtrace_execute;
686+
zend_execute_ex = dtrace_execute_ex;
687687
zend_execute_internal = dtrace_execute_internal;
688688
#else
689689
zend_compile_file = compile_file;
690-
zend_execute = execute;
690+
zend_execute_ex = execute_ex;
691691
zend_execute_internal = NULL;
692692
#endif /* HAVE_SYS_SDT_H */
693693
zend_compile_string = compile_string;

Zend/zend_compile.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
180180
CG(context).literals_size = 0;
181181
CG(context).current_brk_cont = -1;
182182
CG(context).backpatch_count = 0;
183+
CG(context).nested_calls = 0;
184+
CG(context).used_stack = 0;
183185
CG(context).labels = NULL;
184186
}
185187
/* }}} */
@@ -286,7 +288,7 @@ ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
286288

287289
static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
288290
{
289-
return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
291+
return EX_TMP_VAR_NUM(0, (op_array->T)++);
290292
}
291293
/* }}} */
292294

@@ -2328,6 +2330,9 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
23282330
function_name->u.constant.value.str.val = lcname;
23292331

23302332
zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *));
2333+
if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
2334+
CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
2335+
}
23312336
zend_do_extended_fcall_begin(TSRMLS_C);
23322337
return 0;
23332338
}
@@ -2366,11 +2371,13 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
23662371
GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
23672372
}
23682373
last_op->opcode = ZEND_INIT_METHOD_CALL;
2369-
SET_UNUSED(last_op->result);
2374+
last_op->result_type = IS_UNUSED;
2375+
last_op->result.num = CG(context).nested_calls;
23702376
Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
23712377
} else {
23722378
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
23732379
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2380+
opline->result.num = CG(context).nested_calls;
23742381
SET_UNUSED(opline->op1);
23752382
if (left_bracket->op_type == IS_CONST) {
23762383
opline->op2_type = IS_CONST;
@@ -2382,6 +2389,9 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
23822389
}
23832390

23842391
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
2392+
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2393+
CG(active_op_array)->nested_calls = CG(context).nested_calls;
2394+
}
23852395
zend_do_extended_fcall_begin(TSRMLS_C);
23862396
}
23872397
/* }}} */
@@ -2409,12 +2419,14 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
24092419
/* In run-time PHP will check for function with full name and
24102420
internal function with short name */
24112421
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
2422+
opline->result.num = CG(context).nested_calls;
24122423
SET_UNUSED(opline->op1);
24132424
opline->op2_type = IS_CONST;
24142425
opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
24152426
GET_CACHE_SLOT(opline->op2.constant);
24162427
} else {
24172428
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2429+
opline->result.num = CG(context).nested_calls;
24182430
SET_UNUSED(opline->op1);
24192431
if (function_name->op_type == IS_CONST) {
24202432
opline->op2_type = IS_CONST;
@@ -2426,6 +2438,9 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
24262438
}
24272439

24282440
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
2441+
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2442+
CG(active_op_array)->nested_calls = CG(context).nested_calls;
2443+
}
24292444
zend_do_extended_fcall_begin(TSRMLS_C);
24302445
}
24312446
/* }}} */
@@ -2773,6 +2788,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
27732788
opline->extended_value = class_node.EA ;
27742789
}
27752790
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2791+
opline->result.num = CG(context).nested_calls;
27762792
if (class_node.op_type == IS_CONST) {
27772793
opline->op1_type = IS_CONST;
27782794
opline->op1.constant =
@@ -2794,6 +2810,9 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
27942810
}
27952811

27962812
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
2813+
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2814+
CG(active_op_array)->nested_calls = CG(context).nested_calls;
2815+
}
27972816
zend_do_extended_fcall_begin(TSRMLS_C);
27982817
return 1; /* Dynamic */
27992818
}
@@ -2814,21 +2833,29 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
28142833
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
28152834
opline->opcode = ZEND_DO_FCALL;
28162835
SET_NODE(opline->op1, function_name);
2836+
SET_UNUSED(opline->op2);
2837+
opline->op2.num = CG(context).nested_calls;
28172838
CALCULATE_LITERAL_HASH(opline->op1.constant);
28182839
GET_CACHE_SLOT(opline->op1.constant);
28192840
} else {
28202841
opline->opcode = ZEND_DO_FCALL_BY_NAME;
28212842
SET_UNUSED(opline->op1);
2843+
SET_UNUSED(opline->op2);
2844+
opline->op2.num = --CG(context).nested_calls;
28222845
}
28232846
}
28242847

28252848
opline->result.var = get_temporary_variable(CG(active_op_array));
28262849
opline->result_type = IS_VAR;
2827-
GET_NODE(result, opline->result) ;
2828-
SET_UNUSED(opline->op2);
2850+
GET_NODE(result, opline->result);
28292851

28302852
zend_stack_del_top(&CG(function_call_stack));
28312853
opline->extended_value = Z_LVAL(argument_list->u.constant);
2854+
2855+
if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
2856+
CG(active_op_array)->used_stack = CG(context).used_stack + 1;
2857+
}
2858+
CG(context).used_stack -= Z_LVAL(argument_list->u.constant);
28322859
}
28332860
/* }}} */
28342861

@@ -2936,6 +2963,10 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
29362963
SET_NODE(opline->op1, param);
29372964
opline->op2.opline_num = offset;
29382965
SET_UNUSED(opline->op2);
2966+
2967+
if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
2968+
CG(active_op_array)->used_stack = CG(context).used_stack;
2969+
}
29392970
}
29402971
/* }}} */
29412972

@@ -6034,12 +6065,16 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
60346065
new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
60356066
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
60366067
opline->opcode = ZEND_NEW;
6068+
opline->extended_value = CG(context).nested_calls;
60376069
opline->result_type = IS_VAR;
60386070
opline->result.var = get_temporary_variable(CG(active_op_array));
60396071
SET_NODE(opline->op1, class_type);
60406072
SET_UNUSED(opline->op2);
60416073

60426074
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
6075+
if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
6076+
CG(active_op_array)->nested_calls = CG(context).nested_calls;
6077+
}
60436078
}
60446079
/* }}} */
60456080

@@ -6252,6 +6287,13 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
62526287
opline->extended_value = 1;
62536288
SET_UNUSED(opline->op2);
62546289
GET_NODE(result, opline->result);
6290+
6291+
if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
6292+
CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
6293+
}
6294+
if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) {
6295+
CG(active_op_array)->used_stack = CG(context).used_stack + 2;
6296+
}
62556297
}
62566298
/* }}} */
62576299

Zend/zend_compile.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ typedef struct _zend_compiler_context {
8080
int literals_size;
8181
int current_brk_cont;
8282
int backpatch_count;
83+
int nested_calls;
84+
int used_stack;
8385
HashTable *labels;
8486
} zend_compiler_context;
8587

@@ -312,6 +314,9 @@ struct _zend_op_array {
312314

313315
zend_uint T;
314316

317+
zend_uint nested_calls;
318+
zend_uint used_stack;
319+
315320
zend_brk_cont_element *brk_cont_array;
316321
int last_brk_cont;
317322

@@ -416,15 +421,19 @@ typedef struct _list_llist_element {
416421

417422
union _temp_variable;
418423

424+
typedef struct _call_slot {
425+
zend_function *fbc;
426+
zval *object;
427+
zend_class_entry *called_scope;
428+
zend_bool is_ctor_call;
429+
zend_bool is_ctor_result_used;
430+
} call_slot;
431+
419432
struct _zend_execute_data {
420433
struct _zend_op *opline;
421434
zend_function_state function_state;
422-
zend_function *fbc; /* Function Being Called */
423-
zend_class_entry *called_scope;
424435
zend_op_array *op_array;
425436
zval *object;
426-
union _temp_variable *Ts;
427-
zval ***CVs;
428437
HashTable *symbol_table;
429438
struct _zend_execute_data *prev_execute_data;
430439
zval *old_error_reporting;
@@ -433,12 +442,18 @@ struct _zend_execute_data {
433442
zend_class_entry *current_scope;
434443
zend_class_entry *current_called_scope;
435444
zval *current_this;
436-
zval *current_object;
437445
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
446+
call_slot *call_slots;
447+
call_slot *call;
438448
};
439449

440450
#define EX(element) execute_data.element
441451

452+
#define EX_TMP_VAR(ex, n) ((temp_variable*)(((char*)(ex)) + ((int)(n))))
453+
#define EX_TMP_VAR_NUM(ex, n) (EX_TMP_VAR(ex, 0) - (1 + (n)))
454+
455+
#define EX_CV_NUM(ex, n) (((zval***)(((char*)(ex))+ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))))+(n))
456+
442457

443458
#define IS_CONST (1<<0)
444459
#define IS_TMP_VAR (1<<1)

Zend/zend_dtrace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int t
4444
}
4545

4646
/* We wrap the execute function to have fire the execute-entry/return and function-entry/return probes */
47-
ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC)
47+
ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
4848
{
4949
int lineno;
5050
char *scope, *filename, *funcname, *classname;
@@ -72,7 +72,7 @@ ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC)
7272
DTRACE_FUNCTION_ENTRY(funcname, filename, lineno, classname, scope);
7373
}
7474

75-
execute(op_array TSRMLS_CC);
75+
execute_ex(execute_data TSRMLS_CC);
7676

7777
if (DTRACE_FUNCTION_RETURN_ENABLED() && funcname != NULL) {
7878
DTRACE_FUNCTION_RETURN(funcname, filename, lineno, classname, scope);

Zend/zend_dtrace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC);
3535
ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
3636

3737
ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
38-
ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC);
38+
ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC);
3939
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
4040
#include <zend_dtrace_gen.h>
4141

0 commit comments

Comments
 (0)