Skip to content

Commit

Permalink
Improve implementation
Browse files Browse the repository at this point in the history
Use estrndup() over strndup()
Free allocated memory
Only duplicate yytext when neccesary
  • Loading branch information
tpunt committed Dec 29, 2015
1 parent 7435a31 commit b03c616
Showing 1 changed file with 69 additions and 12 deletions.
81 changes: 69 additions & 12 deletions Zend/zend_language_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -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; \
Expand Down Expand Up @@ -1617,10 +1624,15 @@ NEWLINE ("\r"|"\n"|"\r\n")

<ST_IN_SCRIPTING>{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') {
Expand All @@ -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);
}
}

<ST_IN_SCRIPTING>{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;
Expand All @@ -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 {
Expand All @@ -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);
}

<ST_IN_SCRIPTING>{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') {
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -1747,14 +1796,22 @@ string:

<ST_IN_SCRIPTING>{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);
}

Expand Down

0 comments on commit b03c616

Please sign in to comment.