Optimize substr() edge-case conditions

This commit is contained in:
Dmitry Stogov 2018-10-29 13:11:41 +03:00
parent 52d91260df
commit 359f19edc9

View file

@ -2415,52 +2415,53 @@ PHP_FUNCTION(substr)
Z_PARAM_LONG(l) Z_PARAM_LONG(l)
ZEND_PARSE_PARAMETERS_END(); ZEND_PARSE_PARAMETERS_END();
if (argc > 2) { if (f > (zend_long)ZSTR_LEN(str)) {
if ((l < 0 && (size_t)(-l) > ZSTR_LEN(str))) { RETURN_FALSE;
RETURN_FALSE; } else if (f < 0) {
} else if (l > (zend_long)ZSTR_LEN(str)) { /* if "from" position is negative, count start position from the end
l = ZSTR_LEN(str); * of the string
*/
if ((size_t)-f > ZSTR_LEN(str)) {
f = 0;
} else {
f = (zend_long)ZSTR_LEN(str) + f;
}
if (argc > 2) {
if (l < 0) {
/* if "length" position is negative, set it to the length
* needed to stop that many chars from the end of the string
*/
if ((size_t)(-l) > ZSTR_LEN(str) - (size_t)f) {
if ((size_t)(-l) > ZSTR_LEN(str)) {
RETURN_FALSE;
} else {
l = 0;
}
} else {
l = (zend_long)ZSTR_LEN(str) - f + l;
}
} else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
goto truncate_len;
}
} else {
goto truncate_len;
}
} else if (argc > 2) {
if (l < 0) {
/* if "length" position is negative, set it to the length
* needed to stop that many chars from the end of the string
*/
if ((size_t)(-l) > ZSTR_LEN(str) - (size_t)f) {
RETURN_FALSE;
} else {
l = (zend_long)ZSTR_LEN(str) - f + l;
}
} else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
goto truncate_len;
} }
} else { } else {
l = ZSTR_LEN(str); truncate_len:
} l = (zend_long)ZSTR_LEN(str) - f;
if (f > (zend_long)ZSTR_LEN(str)) {
RETURN_FALSE;
} else if (f < 0 && (size_t)-f > ZSTR_LEN(str)) {
f = 0;
}
if (l < 0 && (l + (zend_long)ZSTR_LEN(str) - f) < 0) {
RETURN_FALSE;
}
/* if "from" position is negative, count start position from the end
* of the string
*/
if (f < 0) {
f = (zend_long)ZSTR_LEN(str) + f;
if (f < 0) {
f = 0;
}
}
/* if "length" position is negative, set it to the length
* needed to stop that many chars from the end of the string
*/
if (l < 0) {
l = ((zend_long)ZSTR_LEN(str) - f) + l;
if (l < 0) {
l = 0;
}
}
if (f > (zend_long)ZSTR_LEN(str)) {
RETURN_FALSE;
}
if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
l = ZSTR_LEN(str) - f;
} }
if (l == 0) { if (l == 0) {