]> granicus.if.org Git - php/commitdiff
Fixed bug #73374
authorLeigh <leigh@php.net>
Mon, 31 Oct 2016 16:25:33 +0000 (16:25 +0000)
committerNikita Popov <nikic@php.net>
Thu, 12 Jan 2017 17:53:28 +0000 (18:53 +0100)
Add "0b" prefix detection to intval($str, 0). The implementation
is relatively complicated because we need to handle whitespace and
sign.

NEWS
ext/standard/tests/general_functions/intval_binary_prefix.phpt [new file with mode: 0644]
ext/standard/type.c

diff --git a/NEWS b/NEWS
index a8eeb9a787ffc8bbce4504965ea4636e8c03661f..2a4b137417c382c5671d16a3b998cbe153a57753 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,7 @@ PHP                                                                        NEWS
     "Transfer-Encoding: chunked"). (Rowan Collins)
   . Fixed bug #72974 (imap is undefined service on AIX). (matthieu.sarter)
   . Fixed bug #72979 (money_format stores wrong length AIX). (matthieu.sarter)
+  . Fixed bug #73374 (intval() with base 0 should detect binary). (Leigh)
 
 - ZIP:
   . Fixed bug #70103 (ZipArchive::addGlob ignores remove_all_path option). (cmb,
diff --git a/ext/standard/tests/general_functions/intval_binary_prefix.phpt b/ext/standard/tests/general_functions/intval_binary_prefix.phpt
new file mode 100644 (file)
index 0000000..af49515
--- /dev/null
@@ -0,0 +1,119 @@
+--TEST--
+Test intval() function with "0b" string prefix
+--SKIPIF--
+--FILE--
+<?php
+
+$isspaceChars = " \t\n\r\f\v";
+
+$goodInputs = [
+    '0b1111111111111111111111111111111',
+    '+0b1111111111111111111111111111111',
+    '-0b1111111111111111111111111111111',
+    $isspaceChars . '0b1111111111111111111111111111111',
+    $isspaceChars . '+0b1111111111111111111111111111111',
+    $isspaceChars . '-0b1111111111111111111111111111111',
+    '0b',
+    '0B',
+    '0B1',
+    '0b000',
+    '0b001',
+    '0b00100',
+    '0b1 1'
+];
+
+$badInputs = [
+    'b101',
+    '0b00200',
+    '--0b123',
+    '++0b123',
+    '0bb123',
+    '0 b123',
+];
+
+print "--- Good Inputs - Base = 0 ---\n";
+
+foreach ($goodInputs as $input) {
+    var_dump(
+        intval($input, 0)
+    );
+}
+
+print "--- Good Inputs - Base = 2 ---\n";
+
+foreach ($goodInputs as $input) {
+    var_dump(
+        intval($input, 2)
+    );
+}
+
+print "--- Good Inputs - Base = default ---\n";
+
+foreach ($goodInputs as $input) {
+    var_dump(
+        intval($input)
+    );
+}
+
+print "--- Bad Inputs - Base = 0 ---\n";
+
+foreach ($badInputs as $input) {
+    var_dump(
+        intval($input, 0)
+    );
+}
+
+print '--- Done ---';
+
+?>
+--EXPECTF--
+--- Good Inputs - Base = 0 ---
+int(2147483647)
+int(2147483647)
+int(-2147483647)
+int(2147483647)
+int(2147483647)
+int(-2147483647)
+int(0)
+int(0)
+int(1)
+int(0)
+int(1)
+int(4)
+int(1)
+--- Good Inputs - Base = 2 ---
+int(2147483647)
+int(2147483647)
+int(-2147483647)
+int(2147483647)
+int(2147483647)
+int(-2147483647)
+int(0)
+int(0)
+int(1)
+int(0)
+int(1)
+int(4)
+int(1)
+--- Good Inputs - Base = default ---
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+--- Bad Inputs - Base = 0 ---
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+int(0)
+--- Done ---
index 0c7be1f177ee97c73d4a0cf6d24c7e68b34f9333..d022a1eda3a6802f1057b3ceab47be1db202e649 100644 (file)
@@ -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));
 }
 /* }}} */