Skip to content

Commit 4f7b498

Browse files
ltnikic
authored andcommitted
Fixed bug #73374
Add "0b" prefix detection to intval($str, 0). The implementation is relatively complicated because we need to handle whitespace and sign.
1 parent e65760f commit 4f7b498

File tree

3 files changed

+161
-2
lines changed

3 files changed

+161
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ PHP NEWS
3333
"Transfer-Encoding: chunked"). (Rowan Collins)
3434
. Fixed bug #72974 (imap is undefined service on AIX). (matthieu.sarter)
3535
. Fixed bug #72979 (money_format stores wrong length AIX). (matthieu.sarter)
36+
. Fixed bug #73374 (intval() with base 0 should detect binary). (Leigh)
3637

3738
- ZIP:
3839
. Fixed bug #70103 (ZipArchive::addGlob ignores remove_all_path option). (cmb,
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
--TEST--
2+
Test intval() function with "0b" string prefix
3+
--SKIPIF--
4+
--FILE--
5+
<?php
6+
7+
$isspaceChars = " \t\n\r\f\v";
8+
9+
$goodInputs = [
10+
'0b1111111111111111111111111111111',
11+
'+0b1111111111111111111111111111111',
12+
'-0b1111111111111111111111111111111',
13+
$isspaceChars . '0b1111111111111111111111111111111',
14+
$isspaceChars . '+0b1111111111111111111111111111111',
15+
$isspaceChars . '-0b1111111111111111111111111111111',
16+
'0b',
17+
'0B',
18+
'0B1',
19+
'0b000',
20+
'0b001',
21+
'0b00100',
22+
'0b1 1'
23+
];
24+
25+
$badInputs = [
26+
'b101',
27+
'0b00200',
28+
'--0b123',
29+
'++0b123',
30+
'0bb123',
31+
'0 b123',
32+
];
33+
34+
print "--- Good Inputs - Base = 0 ---\n";
35+
36+
foreach ($goodInputs as $input) {
37+
var_dump(
38+
intval($input, 0)
39+
);
40+
}
41+
42+
print "--- Good Inputs - Base = 2 ---\n";
43+
44+
foreach ($goodInputs as $input) {
45+
var_dump(
46+
intval($input, 2)
47+
);
48+
}
49+
50+
print "--- Good Inputs - Base = default ---\n";
51+
52+
foreach ($goodInputs as $input) {
53+
var_dump(
54+
intval($input)
55+
);
56+
}
57+
58+
print "--- Bad Inputs - Base = 0 ---\n";
59+
60+
foreach ($badInputs as $input) {
61+
var_dump(
62+
intval($input, 0)
63+
);
64+
}
65+
66+
print '--- Done ---';
67+
68+
?>
69+
--EXPECTF--
70+
--- Good Inputs - Base = 0 ---
71+
int(2147483647)
72+
int(2147483647)
73+
int(-2147483647)
74+
int(2147483647)
75+
int(2147483647)
76+
int(-2147483647)
77+
int(0)
78+
int(0)
79+
int(1)
80+
int(0)
81+
int(1)
82+
int(4)
83+
int(1)
84+
--- Good Inputs - Base = 2 ---
85+
int(2147483647)
86+
int(2147483647)
87+
int(-2147483647)
88+
int(2147483647)
89+
int(2147483647)
90+
int(-2147483647)
91+
int(0)
92+
int(0)
93+
int(1)
94+
int(0)
95+
int(1)
96+
int(4)
97+
int(1)
98+
--- Good Inputs - Base = default ---
99+
int(0)
100+
int(0)
101+
int(0)
102+
int(0)
103+
int(0)
104+
int(0)
105+
int(0)
106+
int(0)
107+
int(0)
108+
int(0)
109+
int(0)
110+
int(0)
111+
int(0)
112+
--- Bad Inputs - Base = 0 ---
113+
int(0)
114+
int(0)
115+
int(0)
116+
int(0)
117+
int(0)
118+
int(0)
119+
--- Done ---

ext/standard/type.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,48 @@ PHP_FUNCTION(intval)
150150

151151
if (Z_TYPE_P(num) != IS_STRING || base == 10) {
152152
RETVAL_LONG(zval_get_long(num));
153-
} else {
154-
RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
153+
return;
154+
}
155+
156+
157+
if (base == 0 || base == 2) {
158+
char *strval = Z_STRVAL_P(num);
159+
size_t strlen = Z_STRLEN_P(num);
160+
161+
while (isspace(*strval) && strlen) {
162+
strval++;
163+
strlen--;
164+
}
165+
166+
/* Length of 3+ covers "0b#" and "-0b" (which results in 0) */
167+
if (strlen > 2) {
168+
int offset = 0;
169+
if (strval[0] == '-' || strval[0] == '+') {
170+
offset = 1;
171+
}
172+
173+
if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) {
174+
char *tmpval;
175+
strlen -= 2; /* Removing "0b" */
176+
tmpval = emalloc(strlen + 1);
177+
178+
/* Place the unary symbol at pos 0 if there was one */
179+
if (offset) {
180+
tmpval[0] = strval[0];
181+
}
182+
183+
/* Copy the data from after "0b" to the end of the buffer */
184+
memcpy(tmpval + offset, strval + offset + 2, strlen - offset);
185+
tmpval[strlen] = 0;
186+
187+
RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2));
188+
efree(tmpval);
189+
return;
190+
}
191+
}
155192
}
193+
194+
RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
156195
}
157196
/* }}} */
158197

0 commit comments

Comments
 (0)