]> granicus.if.org Git - php/commitdiff
Optimize substr() edge-case conditions
authorDmitry Stogov <dmitry@zend.com>
Mon, 29 Oct 2018 10:11:41 +0000 (13:11 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 29 Oct 2018 10:11:41 +0000 (13:11 +0300)
ext/standard/string.c

index 2f20d62a7485b5b7b921c2522f0f1233bc050e6a..b28ad050d7bffa9133b9a7750af646839d8e13cf 100644 (file)
@@ -2415,52 +2415,53 @@ PHP_FUNCTION(substr)
                Z_PARAM_LONG(l)
        ZEND_PARSE_PARAMETERS_END();
 
-       if (argc > 2) {
-               if ((l < 0 && (size_t)(-l) > ZSTR_LEN(str))) {
-                       RETURN_FALSE;
-               } else if (l > (zend_long)ZSTR_LEN(str)) {
-                       l = ZSTR_LEN(str);
-               }
-       } else {
-               l = ZSTR_LEN(str);
-       }
-
        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) {
+       } else if (f < 0) {
+               /* if "from" position is negative, count start position from the end
+                * of the string
+                */
+               if ((size_t)-f > ZSTR_LEN(str)) {
                        f = 0;
+               } else {
+                       f = (zend_long)ZSTR_LEN(str) + f;
                }
-       }
-
-       /* 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 (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) {
-                       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;
                }
-       }
-
-       if (f > (zend_long)ZSTR_LEN(str)) {
-               RETURN_FALSE;
-       }
-
-       if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
-               l = ZSTR_LEN(str) - f;
+       } else {
+truncate_len:
+               l = (zend_long)ZSTR_LEN(str) - f;
        }
 
        if (l == 0) {