summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/bug77738.phpt8
-rw-r--r--Zend/zend_compile.c4
-rw-r--r--ext/bcmath/libbcmath/src/num2long.c17
3 files changed, 22 insertions, 7 deletions
diff --git a/Zend/tests/bug77738.phpt b/Zend/tests/bug77738.phpt
new file mode 100644
index 0000000000..e3a453c405
--- /dev/null
+++ b/Zend/tests/bug77738.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #77738 (Nullptr deref in zend_compile_expr)
+--FILE--
+<?php
+__COMPILER_HALT_OFFSET__;
+; // <- important
+--EXPECTF--
+Warning: Use of undefined constant __COMPILER_HALT_OFFSET__ - assumed '__COMPILER_HALT_OFFSET__' %sbug77738.php on line %d
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index bb27b6e63f..2fa847d180 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -7704,11 +7704,11 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
if (zend_string_equals_literal(resolved_name, "__COMPILER_HALT_OFFSET__") || (name_ast->attr != ZEND_NAME_RELATIVE && zend_string_equals_literal(orig_name, "__COMPILER_HALT_OFFSET__"))) {
zend_ast *last = CG(ast);
- while (last->kind == ZEND_AST_STMT_LIST) {
+ while (last && last->kind == ZEND_AST_STMT_LIST) {
zend_ast_list *list = zend_ast_get_list(last);
last = list->child[list->children-1];
}
- if (last->kind == ZEND_AST_HALT_COMPILER) {
+ if (last && last->kind == ZEND_AST_HALT_COMPILER) {
result->op_type = IS_CONST;
ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
zend_string_release_ex(resolved_name, 0);
diff --git a/ext/bcmath/libbcmath/src/num2long.c b/ext/bcmath/libbcmath/src/num2long.c
index 3974dcf286..9b6c0d6e8b 100644
--- a/ext/bcmath/libbcmath/src/num2long.c
+++ b/ext/bcmath/libbcmath/src/num2long.c
@@ -53,12 +53,19 @@ bc_num2long (num)
/* Extract the int value, ignore the fraction. */
val = 0;
nptr = num->n_value;
- for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--)
- val = val*BASE + *nptr++;
+ for (index = num->n_len; index > 0; index--) {
+ char n = *nptr++;
- /* Check for overflow. If overflow, return zero. */
- if (index>0) val = 0;
- if (val < 0) val = 0;
+ if (val > LONG_MAX/BASE) {
+ return 0;
+ }
+ val *= BASE;
+
+ if (val > LONG_MAX - n) {
+ return 0;
+ }
+ val += n;
+ }
/* Return the value. */
if (num->n_sign == PLUS)