diff options
author | Leigh <leigh@php.net> | 2016-10-31 16:25:33 +0000 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2017-01-12 18:53:28 +0100 |
commit | 4f7b498d12b04ae25ae59a711e76410e77455a94 (patch) | |
tree | f53448525d23084297d2bc2ba5761d86b5ccf4c2 /ext/standard/type.c | |
parent | e65760f878a116d7ffc858c5a0e30f6075230443 (diff) | |
download | php-git-4f7b498d12b04ae25ae59a711e76410e77455a94.tar.gz |
Fixed bug #73374
Add "0b" prefix detection to intval($str, 0). The implementation
is relatively complicated because we need to handle whitespace and
sign.
Diffstat (limited to 'ext/standard/type.c')
-rw-r--r-- | ext/standard/type.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/ext/standard/type.c b/ext/standard/type.c index 0c7be1f177..d022a1eda3 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -150,9 +150,48 @@ PHP_FUNCTION(intval) if (Z_TYPE_P(num) != IS_STRING || base == 10) { RETVAL_LONG(zval_get_long(num)); - } else { - RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base)); + return; + } + + + if (base == 0 || base == 2) { + char *strval = Z_STRVAL_P(num); + size_t strlen = Z_STRLEN_P(num); + + while (isspace(*strval) && strlen) { + strval++; + strlen--; + } + + /* Length of 3+ covers "0b#" and "-0b" (which results in 0) */ + if (strlen > 2) { + int offset = 0; + if (strval[0] == '-' || strval[0] == '+') { + offset = 1; + } + + if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) { + char *tmpval; + strlen -= 2; /* Removing "0b" */ + tmpval = emalloc(strlen + 1); + + /* Place the unary symbol at pos 0 if there was one */ + if (offset) { + tmpval[0] = strval[0]; + } + + /* Copy the data from after "0b" to the end of the buffer */ + memcpy(tmpval + offset, strval + offset + 2, strlen - offset); + tmpval[strlen] = 0; + + RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2)); + efree(tmpval); + return; + } + } } + + RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base)); } /* }}} */ |