Skip to content

Commit d90cdbd

Browse files
exussum12nikic
authored andcommitted
Deprecate passing invalid character to base_convert etc
RFC: https://wiki.php.net/rfc/base_convert_improvements
1 parent 550c2aa commit d90cdbd

17 files changed

+470
-20
lines changed

UPGRADING

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ r SQLite3:
348348
in the documentation since PHP 7.1, but did not throw a deprecation notice
349349
for technical reasons.
350350

351+
- Standard:
352+
. Passing invalid characters to ''base_convert()'', ''bindec()'', ''octdec()''
353+
and ''hexdec()'' will now generate a deprecation notice. The result will
354+
still be computed as if the invalid characters did not exist. Leading and
355+
trailing whitespace, as well as prefixes of type 0x (depending on base)
356+
continue to be allowed.
357+
351358
========================================
352359
5. Changed Functions
353360
========================================

ext/standard/math.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -850,22 +850,33 @@ PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
850850
{
851851
zend_long num = 0;
852852
double fnum = 0;
853-
zend_long i;
854853
int mode = 0;
855-
char c, *s;
854+
char c, *s, *e;
856855
zend_long cutoff;
857856
int cutlim;
857+
int invalidchars = 0;
858858

859859
if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
860860
return FAILURE;
861861
}
862-
863862
s = Z_STRVAL_P(arg);
863+
e = s + Z_STRLEN_P(arg);
864+
865+
/* Skip leading whitespace */
866+
while (s < e && isspace(*s)) s++;
867+
/* Skip trailing whitespace */
868+
while (s < e && isspace(*(e-1))) e--;
869+
870+
if (e - s >= 2) {
871+
if (base == 16 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2;
872+
if (base == 8 && s[0] == '0' && (s[1] == 'o' || s[1] == 'O')) s += 2;
873+
if (base == 2 && s[0] == '0' && (s[1] == 'b' || s[1] == 'B')) s += 2;
874+
}
864875

865876
cutoff = ZEND_LONG_MAX / base;
866877
cutlim = ZEND_LONG_MAX % base;
867878

868-
for (i = Z_STRLEN_P(arg); i > 0; i--) {
879+
while (s < e) {
869880
c = *s++;
870881

871882
/* might not work for EBCDIC */
@@ -875,11 +886,15 @@ PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
875886
c -= 'A' - 10;
876887
else if (c >= 'a' && c <= 'z')
877888
c -= 'a' - 10;
878-
else
889+
else {
890+
invalidchars++;
879891
continue;
892+
}
880893

881-
if (c >= base)
894+
if (c >= base) {
895+
invalidchars++;
882896
continue;
897+
}
883898

884899
switch (mode) {
885900
case 0: /* Integer */
@@ -896,6 +911,10 @@ PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
896911
}
897912
}
898913

914+
if (invalidchars > 0) {
915+
zend_error(E_DEPRECATED, "Invalid characters passed for attempted conversion, these have been ignored");
916+
}
917+
899918
if (mode == 1) {
900919
ZVAL_DOUBLE(ret, fnum);
901920
} else {

0 commit comments

Comments
 (0)