From b03c6164a49aec8632b5b530eb12dc0b931bef60 Mon Sep 17 00:00:00 2001 From: Thomas Punt Date: Tue, 29 Dec 2015 22:19:33 +0000 Subject: [PATCH] Improve implementation Use estrndup() over strndup() Free allocated memory Only duplicate yytext when neccesary --- Zend/zend_language_scanner.l | 81 ++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 1b9a5b3b13b6b..1c023649450be 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -112,6 +112,13 @@ do { \ } \ } +#define CONTAINS_UNDERSCORES(n, len, res) \ +{ \ + int i; \ + for (i = 0; i < len && n[i] != '_'; ++i); \ + res = i != len; \ +} + #define STRIP_UNDERSCORES(n, len) \ { \ int i, old_len = len; \ @@ -1617,10 +1624,15 @@ NEWLINE ("\r"|"\n"|"\r\n") {BNUM} { /* The +/- 2 skips "0b" */ - int len = yyleng - 2; - char *end, *bin = strndup(yytext + 2, len); + int len = yyleng - 2, contains_underscores; + char *end, *bin = yytext + 2; - STRIP_UNDERSCORES(bin, len) + CONTAINS_UNDERSCORES(bin, len, contains_underscores) + + if (contains_underscores) { + bin = estrndup(bin, len); + STRIP_UNDERSCORES(bin, len) + } /* Skip any leading 0s */ while (*bin == '0') { @@ -1636,20 +1648,31 @@ NEWLINE ("\r"|"\n"|"\r\n") ZVAL_LONG(zendlval, ZEND_STRTOL(bin, &end, 2)); ZEND_ASSERT(!errno && end == yytext + yyleng); } + if (contains_underscores) { + efree(bin); + } RETURN_TOKEN(T_LNUMBER); } else { ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, (const char **)&end)); /* errno isn't checked since we allow HUGE_VAL/INF overflow */ ZEND_ASSERT(end == yytext + yyleng); + if (contains_underscores) { + efree(bin); + } RETURN_TOKEN(T_DNUMBER); } } {LNUM} { - int len = yyleng; - char *end, *lnum = strndup(yytext, yyleng); + int len = yyleng, contains_underscores; + char *end, *lnum = yytext; + + CONTAINS_UNDERSCORES(lnum, len, contains_underscores) - STRIP_UNDERSCORES(lnum, len) + if (contains_underscores) { + lnum = estrndup(lnum, len); + STRIP_UNDERSCORES(lnum, len) + } if (len < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ errno = 0; @@ -1660,6 +1683,9 @@ NEWLINE ("\r"|"\n"|"\r\n") if (end != lnum + len) { zend_throw_exception(zend_ce_parse_error, "Invalid numeric literal", 0); ZVAL_UNDEF(zendlval); + if (contains_underscores) { + efree(lnum); + } RETURN_TOKEN(T_LNUMBER); } } else { @@ -1678,28 +1704,45 @@ NEWLINE ("\r"|"\n"|"\r\n") zend_throw_exception(zend_ce_parse_error, "Invalid numeric literal", 0); ZVAL_UNDEF(zendlval); + if (contains_underscores) { + efree(lnum); + } RETURN_TOKEN(T_DNUMBER); } ZEND_ASSERT(!errno); + if (contains_underscores) { + efree(lnum); + } RETURN_TOKEN(T_DNUMBER); } /* Also not an assert for the same reason */ if (end != lnum + len) { zend_throw_exception(zend_ce_parse_error, "Invalid numeric literal", 0); ZVAL_UNDEF(zendlval); + if (contains_underscores) { + efree(lnum); + } RETURN_TOKEN(T_DNUMBER); } } ZEND_ASSERT(!errno); + if (contains_underscores) { + efree(lnum); + } RETURN_TOKEN(T_LNUMBER); } {HNUM} { /* The +/- 2 skips "0x" */ - int len = yyleng - 2; - char *end, *hex = strndup(yytext + 2, len); + int len = yyleng - 2, contains_underscores; + char *end, *hex = yytext + 2; - STRIP_UNDERSCORES(hex, len) + CONTAINS_UNDERSCORES(hex, len, contains_underscores) + + if (contains_underscores) { + hex = estrndup(hex, len); + STRIP_UNDERSCORES(hex, len) + } /* Skip any leading 0s */ while (*hex == '0') { @@ -1715,11 +1758,17 @@ NEWLINE ("\r"|"\n"|"\r\n") ZVAL_LONG(zendlval, ZEND_STRTOL(hex, &end, 16)); ZEND_ASSERT(!errno && end == hex + len); } + if (contains_underscores) { + efree(hex); + } RETURN_TOKEN(T_LNUMBER); } else { ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, (const char **)&end)); /* errno isn't checked since we allow HUGE_VAL/INF overflow */ ZEND_ASSERT(end == hex + len); + if (contains_underscores) { + efree(hex); + } RETURN_TOKEN(T_DNUMBER); } } @@ -1747,14 +1796,22 @@ string: {DNUM}|{EXPONENT_DNUM} { const char *end; - int len = yyleng; - char *dnum = strndup(yytext, yyleng); + int len = yyleng, contains_underscores; + char *dnum = yytext; - STRIP_UNDERSCORES(dnum, len) + CONTAINS_UNDERSCORES(dnum, len, contains_underscores) + + if (contains_underscores) { + dnum = estrndup(dnum, len); + STRIP_UNDERSCORES(dnum, len) + } ZVAL_DOUBLE(zendlval, zend_strtod(dnum, &end)); /* errno isn't checked since we allow HUGE_VAL/INF overflow */ ZEND_ASSERT(end == dnum + len); + if (contains_underscores) { + efree(dnum); + } RETURN_TOKEN(T_DNUMBER); }