Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

- Add foreach() freeing code.

- Fix switch() freeing code to only free current function's switch expressions.
- I have a feeling break expr; in a switch where expr > 1 leaks because it
  won't free all of the expressions. Fix is probably not trivial.
  • Loading branch information...
commit 22f066e708e95debf48065563671d78619807651 1 parent 7567b96
andigutmans andigutmans authored
55 Zend/zend_compile.c
@@ -82,6 +82,7 @@ void init_compiler(CLS_D ELS_DC)
82 82 zend_stack_init(&CG(bp_stack));
83 83 zend_stack_init(&CG(function_call_stack));
84 84 zend_stack_init(&CG(switch_cond_stack));
  85 + zend_stack_init(&CG(foreach_copy_stack));
85 86 zend_stack_init(&CG(object_stack));
86 87 CG(active_class_entry) = NULL;
87 88 zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
@@ -102,6 +103,7 @@ void shutdown_compiler(CLS_D)
102 103 zend_stack_destroy(&CG(bp_stack));
103 104 zend_stack_destroy(&CG(function_call_stack));
104 105 zend_stack_destroy(&CG(switch_cond_stack));
  106 + zend_stack_destroy(&CG(foreach_copy_stack));
105 107 zend_stack_destroy(&CG(object_stack));
106 108 zend_llist_destroy(&CG(filenames_list));
107 109 zend_hash_apply(CG(function_table), (int (*)(void *)) is_not_internal_function);
@@ -667,6 +669,19 @@ void do_begin_function_declaration(znode *function_token, znode *function_name,
667 669 SET_UNUSED(opline->op1);
668 670 SET_UNUSED(opline->op2);
669 671 }
  672 +
  673 + {
  674 + /* Push a seperator to the switch and foreach stacks */
  675 + zend_switch_entry switch_entry;
  676 +
  677 + switch_entry.cond.op_type = IS_UNUSED;
  678 + switch_entry.default_case = 0;
  679 + switch_entry.control_var = 0;
  680 +
  681 + zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
  682 +
  683 + zend_stack_push(&CG(foreach_copy_stack), (void *) &switch_entry.cond, sizeof(znode));
  684 + }
670 685 }
671 686
672 687
@@ -674,6 +689,10 @@ void do_end_function_declaration(znode *function_token CLS_DC)
674 689 {
675 690 pass_two(CG(active_op_array));
676 691 CG(active_op_array) = function_token->u.op_array;
  692 +
  693 + /* Pop the switch and foreach seperators */
  694 + zend_stack_del_top(&CG(switch_cond_stack));
  695 + zend_stack_del_top(&CG(foreach_copy_stack));
677 696 }
678 697
679 698
@@ -856,24 +875,48 @@ void do_pass_param(znode *param, int op, int offset CLS_DC)
856 875 }
857 876
858 877
859   -static void generate_free_switch_expr(zend_switch_entry *switch_entry CLS_DC)
  878 +static int generate_free_switch_expr(zend_switch_entry *switch_entry CLS_DC)
860 879 {
861   - zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
  880 + zend_op *opline;
  881 +
  882 + if (switch_entry->cond.op_type == IS_UNUSED) {
  883 + return 1;
  884 + }
  885 +
  886 + opline = get_next_op(CG(active_op_array) CLS_CC);
862 887
863 888 opline->opcode = ZEND_SWITCH_FREE;
864 889 opline->op1 = switch_entry->cond;
865 890 SET_UNUSED(opline->op2);
  891 + return 0;
866 892 }
867 893
  894 +static int generate_free_foreach_copy(znode *foreach_copy CLS_DC)
  895 +{
  896 + zend_op *opline;
  897 +
  898 + if (foreach_copy->op_type == IS_UNUSED) {
  899 + return 1;
  900 + }
  901 +
  902 + opline = get_next_op(CG(active_op_array) CLS_CC);
  903 +
  904 + opline->opcode = ZEND_FREE;
  905 + opline->op1 = *foreach_copy;
  906 + SET_UNUSED(opline->op2);
  907 + return 0;
  908 +}
868 909
869 910 void do_return(znode *expr CLS_DC)
870 911 {
871 912 zend_op *opline;
872 913
873 914 #ifdef ZTS
874   - zend_stack_apply_with_argument(&CG(switch_cond_stack), (void (*)(void *element, void *)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN CLS_CC);
  915 + zend_stack_apply_with_argument(&CG(switch_cond_stack), (int (*)(void *element, void *)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN CLS_CC);
  916 + zend_stack_apply_with_argument(&CG(foreach_copy_stack), (int (*)(void *element, void *)) generate_free_foreach_copy, ZEND_STACK_APPLY_TOPDOWN CLS_CC);
875 917 #else
876   - zend_stack_apply(&CG(switch_cond_stack), (void (*)(void *element)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN);
  918 + zend_stack_apply(&CG(switch_cond_stack), (int (*)(void *element)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN);
  919 + zend_stack_apply(&CG(foreach_copy_stack), (int (*)(void *element)) generate_free_foreach_copy, ZEND_STACK_APPLY_TOPDOWN);
877 920 #endif
878 921
879 922 opline = get_next_op(CG(active_op_array) CLS_CC);
@@ -1808,6 +1851,8 @@ void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_t
1808 1851 SET_UNUSED(opline->op2);
1809 1852 *open_brackets_token = opline->result;
1810 1853
  1854 + zend_stack_push(&CG(foreach_copy_stack), (void *) &opline->result, sizeof(znode));
  1855 +
1811 1856 /* save the location of the beginning of the loop (array fetching) */
1812 1857 foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
1813 1858
@@ -1887,6 +1932,8 @@ void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC)
1887 1932
1888 1933 do_free(open_brackets_token CLS_CC);
1889 1934
  1935 + zend_stack_del_top(&CG(foreach_copy_stack));
  1936 +
1890 1937 DEC_BPC(CG(active_op_array));
1891 1938 }
1892 1939
1  Zend/zend_globals.h
@@ -58,6 +58,7 @@ END_EXTERN_C()
58 58 struct _zend_compiler_globals {
59 59 zend_stack bp_stack;
60 60 zend_stack switch_cond_stack;
  61 + zend_stack foreach_copy_stack;
61 62 zend_stack object_stack;
62 63
63 64 zend_class_entry class_entry, *active_class_entry;
20 Zend/zend_stack.c
@@ -118,38 +118,46 @@ ZEND_API int zend_stack_count(zend_stack *stack)
118 118 }
119 119
120 120
121   -ZEND_API void zend_stack_apply(zend_stack *stack, void (*apply_function)(void *element), int type)
  121 +ZEND_API void zend_stack_apply(zend_stack *stack, int (*apply_function)(void *element), int type)
122 122 {
123 123 int i;
124 124
125 125 switch (type) {
126 126 case ZEND_STACK_APPLY_TOPDOWN:
127 127 for (i=stack->top-1; i>=0; i--) {
128   - apply_function(stack->elements[i]);
  128 + if (apply_function(stack->elements[i])) {
  129 + break;
  130 + }
129 131 }
130 132 break;
131 133 case ZEND_STACK_APPLY_BOTTOMUP:
132 134 for (i=0; i<stack->top; i++) {
133   - apply_function(stack->elements[i]);
  135 + if (apply_function(stack->elements[i])) {
  136 + break;
  137 + }
134 138 }
135 139 break;
136 140 }
137 141 }
138 142
139 143
140   -ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, void (*apply_function)(void *element, void *arg), int type, void *arg)
  144 +ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int (*apply_function)(void *element, void *arg), int type, void *arg)
141 145 {
142 146 int i;
143 147
144 148 switch (type) {
145 149 case ZEND_STACK_APPLY_TOPDOWN:
146 150 for (i=stack->top-1; i>=0; i--) {
147   - apply_function(stack->elements[i], arg);
  151 + if (apply_function(stack->elements[i], arg)) {
  152 + break;
  153 + }
148 154 }
149 155 break;
150 156 case ZEND_STACK_APPLY_BOTTOMUP:
151 157 for (i=0; i<stack->top; i++) {
152   - apply_function(stack->elements[i], arg);
  158 + if (apply_function(stack->elements[i], arg)) {
  159 + break;
  160 + }
153 161 }
154 162 break;
155 163 }
4 Zend/zend_stack.h
@@ -38,8 +38,8 @@ ZEND_API int zend_stack_is_empty(zend_stack *stack);
38 38 ZEND_API int zend_stack_destroy(zend_stack *stack);
39 39 ZEND_API void **zend_stack_base(zend_stack *stack);
40 40 ZEND_API int zend_stack_count(zend_stack *stack);
41   -ZEND_API void zend_stack_apply(zend_stack *stack, void (*apply_function)(void *element), int type);
42   -ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, void (*apply_function)(void *element, void *arg), int type, void *arg);
  41 +ZEND_API void zend_stack_apply(zend_stack *stack, int (*apply_function)(void *element), int type);
  42 +ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int (*apply_function)(void *element, void *arg), int type, void *arg);
43 43
44 44 #define ZEND_STACK_APPLY_TOPDOWN 1
45 45 #define ZEND_STACK_APPLY_BOTTOMUP 2

0 comments on commit 22f066e

Please sign in to comment.
Something went wrong with that request. Please try again.