Skip to content

Commit 0b7dffb

Browse files
committed
Fix #73122: Integer Overflow when concatenating strings
We must avoid integer overflows in memory allocations, so we introduce an additional check in the VM, and bail out in the rare case of an overflow. Closes GH-7381.
1 parent 51147e2 commit 0b7dffb

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ PHP NEWS
66
. Fixed bug #81302 (Stream position after stream filter removed). (cmb)
77
. Fixed bug #81346 (Non-seekable streams don't update position after write).
88
(cmb)
9+
. Fixed bug #73122 (Integer Overflow when concatenating strings). (cmb)
910

1011
- Opcache:
1112
. Fixed bug #81353 (segfault with preloading and statically bound closure).

Zend/zend_vm_def.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
416416
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
417417
size_t len = ZSTR_LEN(op1_str);
418418

419+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
420+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
421+
}
419422
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
420423
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
421424
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);

Zend/zend_vm_execute.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7899,6 +7899,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
78997899
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
79007900
size_t len = ZSTR_LEN(op1_str);
79017901

7902+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
7903+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
7904+
}
79027905
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
79037906
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
79047907
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -10357,6 +10360,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
1035710360
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
1035810361
size_t len = ZSTR_LEN(op1_str);
1035910362

10363+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
10364+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
10365+
}
1036010366
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
1036110367
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
1036210368
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -14674,6 +14680,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
1467414680
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
1467514681
size_t len = ZSTR_LEN(op1_str);
1467614682

14683+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
14684+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
14685+
}
1467714686
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
1467814687
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
1467914688
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -15343,6 +15352,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
1534315352
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
1534415353
size_t len = ZSTR_LEN(op1_str);
1534515354

15355+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
15356+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
15357+
}
1534615358
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
1534715359
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
1534815360
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -17027,6 +17039,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
1702717039
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
1702817040
size_t len = ZSTR_LEN(op1_str);
1702917041

17042+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
17043+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
17044+
}
1703017045
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
1703117046
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
1703217047
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -38332,6 +38347,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
3833238347
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
3833338348
size_t len = ZSTR_LEN(op1_str);
3833438349

38350+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
38351+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
38352+
}
3833538353
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
3833638354
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
3833738355
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -40708,6 +40726,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
4070840726
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
4070940727
size_t len = ZSTR_LEN(op1_str);
4071040728

40729+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
40730+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
40731+
}
4071140732
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
4071240733
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
4071340734
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
@@ -46835,6 +46856,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
4683546856
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
4683646857
size_t len = ZSTR_LEN(op1_str);
4683746858

46859+
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
46860+
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
46861+
}
4683846862
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
4683946863
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
4684046864
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);

0 commit comments

Comments
 (0)