====== PHP RFC: base_convert changes ====== * Version: 0.1 * Date: 2019-05-15 * Author: Scott Dutton,php@exussum.co.uk * Status: Implemented (in PHP 7.4) * First Published at: https://wiki.php.net/rfc/base_convert_improvements ===== Introduction ===== The base_convert family of functions(base_convert, binhex, hexbin etc) are very accepting with their input arguments, you can pass any string to to them and they give a best effort of converting it. For example base_convert("hello world", 16, 10); will return 237 with no warnings. What this does internally is base_convert("ed", 16, 10); Also negative numbers simply do not work, eg base_convert("-ff", 16, 10); will return 255. (similar to above the "-" gets silently ignored). Experienced developers get caught out by this for example https://gist.github.com/iansltx/4820b02ab276c3306314daaa41573445#file-getlines-php-L9 In this case literal binary data was the input and the result was 0 (which is expected but not clear) Other functions affected by this are: * decbin() - Decimal to binary * bindec() - Binary to decimal * decoct() - Decimal to octal * octdec() - Octal to decimal * dechex() - Decimal to hexadecimal * hexdec() - Hexadecimal to decimal Other programming languages behave in a a similar way to this proposal * Javascript - https://jsfiddle.net/c16b4usp/ * Python - https://repl.it/repls/OliveBlushingModem * Go - https://play.golang.org/p/aLWg15c00Fy Javascript does work with larger numbers correctly, Python and Go work in a way which would be similar to PHP if this change was made. ===== Proposal ===== I propose two changes to the base_convert family of functions. === Error on ignored characters === When passed arguments that base_convert will ignore, also give a warning to the user informing them their input was incorrect. There is an exception in place for the second char, if base is 16 'x' is allowed eg "0xff", base 2 allows b and base 8 allows o. this fits in with common formats for these numbers This can be raised to a full exception for a later PHP version (eg PHP 8) === Allow negative arguments === Negative numbers should be allowed to be passed to the base_convert family of functions. for example base_convert('-ff', 16', 10); should return -255. Currently users need to make an exception in this case ===== Backward Incompatible Changes ===== === Error on ignored characters === No BC breaks for a warning, in the case of an exception there will be a BC break - Would suggest PHP 8 for this. === Allow negative arguments === base_convert currently in the backend has a zend_ulong as its representation. We would need a zend_long. This will change the behavior of numbers in the range 9223372036854775807 - 18446744073709551615 but will allow negative numbers. This currently breaks a fair amount of unit tests that I will need to update if this change is accepted. The unit tests are around extreme values. A secondary BC change would be people who have worked around this in userland code for example https://stackoverflow.com/a/7051224/1281385 This change will break these work arounds Would suggest PHP8 for this change ===== Proposed PHP Version(s) ===== PHP 7.4 for warnings PHP 8.0 for negative arguments and exceptions ===== RFC Impact ===== ==== To SAPIs ==== None ==== To Existing Extensions ==== None ==== To Opcache ==== None ==== New Constants ==== None ==== php.ini Defaults ==== ===== Open Issues ===== Make sure there are no open issues when the vote starts! ===== Unaffected PHP Functionality ===== Only the base_convert family of functions will be changed ===== Future Scope ===== Allow base_convert to allow any length input and not be restricted to a 64 bit int type ===== Proposed Voting Choices ===== 2 votes === Error on ignored characters === This vote will be to raise a E_DEPRECATED warning for PHP 7.4. Raising to be an InvalidArgumentException in PHP 8 === Allow negative arguments === This vote will allow negative arguments in PHP 8 ===== Patches and Tests ===== https://github.com/php/php-src/pull/3911 ===== Vote ===== Started 19th June 2019. Ends 3rd July 2019 * Yes * No * Yes * No ===== References ===== https://bugs.php.net/bug.php?id=61740 https://bugs.php.net/bug.php?id=55393 ===== Rejected Features ===== Keep this updated with features that were discussed on the mail lists.