Skip to content

Commit ea09a9f

Browse files
committed
Convert fatal errors into EngineExceptions
Make zval_update_constant_ex(), zval_update_constant(), zend_update_class_constants() and zend_ast_evaluate() return SUCCESS or FAILURE.
1 parent 956fa03 commit ea09a9f

19 files changed

+328
-185
lines changed

Zend/zend_API.c

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset)
11191119
int ret;
11201120
zend_class_entry *old_scope = *scope;
11211121
*scope = prop_info->ce;
1122-
ret = zval_update_constant(pp, 1);
1122+
ret = zval_update_constant_ex(pp, 1, NULL);
11231123
*scope = old_scope;
11241124
return ret;
11251125
}
@@ -1128,13 +1128,13 @@ static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset)
11281128
} while (ce);
11291129

11301130
}
1131-
return zval_update_constant(pp, 1);
1131+
return zval_update_constant_ex(pp, 1, NULL);
11321132
}
1133-
return 0;
1133+
return SUCCESS;
11341134
}
11351135
/* }}} */
11361136

1137-
ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1137+
ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
11381138
{
11391139
int i;
11401140

@@ -1143,7 +1143,9 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ *
11431143
zval *p;
11441144

11451145
if (class_type->parent) {
1146-
zend_update_class_constants(class_type->parent);
1146+
if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1147+
return FAILURE;
1148+
}
11471149
}
11481150
#if ZTS
11491151
CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
@@ -1177,22 +1179,29 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ *
11771179
*scope = class_type;
11781180

11791181
ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
1180-
zval_update_constant(val, 1);
1182+
if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
1183+
return FAILURE;
1184+
}
11811185
} ZEND_HASH_FOREACH_END();
11821186

11831187
for (i = 0; i < class_type->default_properties_count; i++) {
11841188
if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) {
1185-
zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i));
1189+
if (UNEXPECTED(zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i)) != SUCCESS)) {
1190+
return FAILURE;
1191+
}
11861192
}
11871193
}
11881194

11891195
for (i = 0; i < class_type->default_static_members_count; i++) {
1190-
zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i);
1196+
if (UNEXPECTED(zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i) != SUCCESS)) {
1197+
return FAILURE;
1198+
}
11911199
}
11921200

11931201
*scope = old_scope;
11941202
class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
11951203
}
1204+
return SUCCESS;
11961205
}
11971206
/* }}} */
11981207

@@ -1273,15 +1282,22 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
12731282
{
12741283
if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
12751284
if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1276-
zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", class_type->name->val);
1285+
zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", class_type->name->val);
12771286
} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1278-
zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", class_type->name->val);
1287+
zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", class_type->name->val);
12791288
} else {
1280-
zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", class_type->name->val);
1289+
zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", class_type->name->val);
12811290
}
1291+
ZVAL_NULL(arg);
1292+
Z_OBJ_P(arg) = NULL;
1293+
return FAILURE;
12821294
}
12831295

1284-
zend_update_class_constants(class_type);
1296+
if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1297+
ZVAL_NULL(arg);
1298+
Z_OBJ_P(arg) = NULL;
1299+
return FAILURE;
1300+
}
12851301

12861302
if (class_type->create_object == NULL) {
12871303
ZVAL_OBJ(arg, zend_objects_new(class_type));

Zend/zend_API.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,8 @@ ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char
325325
ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length);
326326
ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value);
327327

328-
ZEND_API void zend_update_class_constants(zend_class_entry *class_type);
328+
ZEND_API int zend_update_class_constants(zend_class_entry *class_type);
329+
329330
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value);
330331
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length);
331332
ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value);

Zend/zend_ast.c

Lines changed: 118 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
177177
return (zend_ast *) list;
178178
}
179179

180-
static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
180+
static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
181181
{
182182
switch (Z_TYPE_P(offset)) {
183183
case IS_UNDEF:
@@ -203,68 +203,90 @@ static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
203203
zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
204204
break;
205205
default:
206-
zend_error_noreturn(E_ERROR, "Illegal offset type");
207-
break;
206+
zend_error(E_EXCEPTION | E_ERROR, "Illegal offset type");
207+
return FAILURE;
208208
}
209+
return SUCCESS;
209210
}
210211

211-
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
212+
ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
212213
{
213214
zval op1, op2;
215+
int ret = SUCCESS;
214216

215217
switch (ast->kind) {
216218
case ZEND_AST_BINARY_OP:
217-
{
218-
binary_op_type op = get_binary_op(ast->attr);
219-
zend_ast_evaluate(&op1, ast->child[0], scope);
220-
zend_ast_evaluate(&op2, ast->child[1], scope);
221-
op(result, &op1, &op2);
222-
zval_dtor(&op1);
223-
zval_dtor(&op2);
219+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
220+
ret = FAILURE;
221+
} else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
222+
zval_dtor(&op1);
223+
ret = FAILURE;
224+
} else {
225+
binary_op_type op = get_binary_op(ast->attr);
226+
ret = op(result, &op1, &op2);
227+
zval_dtor(&op1);
228+
zval_dtor(&op2);
229+
}
224230
break;
225-
}
226231
case ZEND_AST_GREATER:
227232
case ZEND_AST_GREATER_EQUAL:
228-
{
229-
/* op1 > op2 is the same as op2 < op1 */
230-
binary_op_type op = ast->kind == ZEND_AST_GREATER
231-
? is_smaller_function : is_smaller_or_equal_function;
232-
zend_ast_evaluate(&op1, ast->child[0], scope);
233-
zend_ast_evaluate(&op2, ast->child[1], scope);
234-
op(result, &op2, &op1);
235-
zval_dtor(&op1);
236-
zval_dtor(&op2);
233+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
234+
ret = FAILURE;
235+
} else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
236+
zval_dtor(&op1);
237+
ret = FAILURE;
238+
} else {
239+
/* op1 > op2 is the same as op2 < op1 */
240+
binary_op_type op = ast->kind == ZEND_AST_GREATER
241+
? is_smaller_function : is_smaller_or_equal_function;
242+
ret = op(result, &op2, &op1);
243+
zval_dtor(&op1);
244+
zval_dtor(&op2);
245+
}
237246
break;
238-
}
239247
case ZEND_AST_UNARY_OP:
240-
{
241-
unary_op_type op = get_unary_op(ast->attr);
242-
zend_ast_evaluate(&op1, ast->child[0], scope);
243-
op(result, &op1);
244-
zval_dtor(&op1);
248+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
249+
ret = FAILURE;
250+
} else {
251+
unary_op_type op = get_unary_op(ast->attr);
252+
ret = op(result, &op1);
253+
zval_dtor(&op1);
254+
}
245255
break;
246-
}
247256
case ZEND_AST_ZVAL:
248257
{
249258
zval *zv = zend_ast_get_zval(ast);
250259
if (scope) {
251260
/* class constants may be updated in-place */
252261
if (Z_OPT_CONSTANT_P(zv)) {
253-
zval_update_constant_ex(zv, 1, scope);
262+
if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) {
263+
ret = FAILURE;
264+
break;
265+
}
254266
}
255267
ZVAL_DUP(result, zv);
256268
} else {
257269
ZVAL_DUP(result, zv);
258270
if (Z_OPT_CONSTANT_P(result)) {
259-
zval_update_constant_ex(result, 1, scope);
271+
if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) {
272+
ret = FAILURE;
273+
break;
274+
}
260275
}
261276
}
262277
break;
263278
}
264279
case ZEND_AST_AND:
265-
zend_ast_evaluate(&op1, ast->child[0], scope);
280+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
281+
ret = FAILURE;
282+
break;
283+
}
266284
if (zend_is_true(&op1)) {
267-
zend_ast_evaluate(&op2, ast->child[1], scope);
285+
if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
286+
zval_dtor(&op1);
287+
ret = FAILURE;
288+
break;
289+
}
268290
ZVAL_BOOL(result, zend_is_true(&op2));
269291
zval_dtor(&op2);
270292
} else {
@@ -273,41 +295,65 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
273295
zval_dtor(&op1);
274296
break;
275297
case ZEND_AST_OR:
276-
zend_ast_evaluate(&op1, ast->child[0], scope);
298+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
299+
ret = FAILURE;
300+
break;
301+
}
277302
if (zend_is_true(&op1)) {
278303
ZVAL_TRUE(result);
279304
} else {
280-
zend_ast_evaluate(&op2, ast->child[1], scope);
305+
if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
306+
zval_dtor(&op1);
307+
ret = FAILURE;
308+
break;
309+
}
281310
ZVAL_BOOL(result, zend_is_true(&op2));
282311
zval_dtor(&op2);
283312
}
284313
zval_dtor(&op1);
285314
break;
286315
case ZEND_AST_CONDITIONAL:
287-
zend_ast_evaluate(&op1, ast->child[0], scope);
316+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
317+
ret = FAILURE;
318+
break;
319+
}
288320
if (zend_is_true(&op1)) {
289321
if (!ast->child[1]) {
290322
*result = op1;
291323
} else {
292-
zend_ast_evaluate(result, ast->child[1], scope);
324+
if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
325+
zval_dtor(&op1);
326+
ret = FAILURE;
327+
break;
328+
}
293329
zval_dtor(&op1);
294330
}
295331
} else {
296-
zend_ast_evaluate(result, ast->child[2], scope);
332+
if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) {
333+
zval_dtor(&op1);
334+
ret = FAILURE;
335+
break;
336+
}
297337
zval_dtor(&op1);
298338
}
299339
break;
300340
case ZEND_AST_UNARY_PLUS:
301-
ZVAL_LONG(&op1, 0);
302-
zend_ast_evaluate(&op2, ast->child[0], scope);
303-
add_function(result, &op1, &op2);
304-
zval_dtor(&op2);
341+
if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
342+
ret = FAILURE;
343+
} else {
344+
ZVAL_LONG(&op1, 0);
345+
ret = add_function(result, &op1, &op2);
346+
zval_dtor(&op2);
347+
}
305348
break;
306349
case ZEND_AST_UNARY_MINUS:
307-
ZVAL_LONG(&op1, 0);
308-
zend_ast_evaluate(&op2, ast->child[0], scope);
309-
sub_function(result, &op1, &op2);
310-
zval_dtor(&op2);
350+
if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
351+
ret = FAILURE;
352+
} else {
353+
ZVAL_LONG(&op1, 0);
354+
ret = sub_function(result, &op1, &op2);
355+
zval_dtor(&op2);
356+
}
311357
break;
312358
case ZEND_AST_ARRAY:
313359
array_init(result);
@@ -317,29 +363,47 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
317363
for (i = 0; i < list->children; i++) {
318364
zend_ast *elem = list->child[i];
319365
if (elem->child[1]) {
320-
zend_ast_evaluate(&op1, elem->child[1], scope);
366+
if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[1], scope) != SUCCESS)) {
367+
zval_dtor(result);
368+
return FAILURE;
369+
}
321370
} else {
322371
ZVAL_UNDEF(&op1);
323372
}
324-
zend_ast_evaluate(&op2, elem->child[0], scope);
325-
zend_ast_add_array_element(result, &op1, &op2);
373+
if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) {
374+
zval_dtor(&op1);
375+
zval_dtor(result);
376+
return FAILURE;
377+
}
378+
if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
379+
zval_dtor(&op1);
380+
zval_dtor(&op2);
381+
zval_dtor(result);
382+
return FAILURE;
383+
}
326384
}
327385
}
328386
break;
329387
case ZEND_AST_DIM:
330-
zend_ast_evaluate(&op1, ast->child[0], scope);
331-
zend_ast_evaluate(&op2, ast->child[1], scope);
332-
{
388+
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
389+
ret = FAILURE;
390+
} else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
391+
zval_dtor(&op1);
392+
ret = FAILURE;
393+
} else {
333394
zval tmp;
395+
334396
zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
335397
ZVAL_ZVAL(result, &tmp, 1, 1);
398+
zval_dtor(&op1);
399+
zval_dtor(&op2);
336400
}
337-
zval_dtor(&op1);
338-
zval_dtor(&op2);
339401
break;
340402
default:
341-
zend_error_noreturn(E_ERROR, "Unsupported constant expression");
403+
zend_error(E_EXCEPTION | E_ERROR, "Unsupported constant expression");
404+
ret = FAILURE;
342405
}
406+
return ret;
343407
}
344408

345409
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)

Zend/zend_ast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ ZEND_API zend_ast *zend_ast_create_decl(
203203
ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...);
204204
ZEND_API zend_ast *zend_ast_list_add(zend_ast *list, zend_ast *op);
205205

206-
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope);
206+
ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope);
207207
ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix);
208208

209209
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);

0 commit comments

Comments
 (0)