In previous blog, I wrote how PHP7’s basic type hinting works and missing piece to make it work. I would like to explain reason why current type hinting design will not work well for PHP.
PHP7’s basic type hinting forces program to use “signed 32 bit integer” or “signed 64 bit integer” depending on CPU. PHP was weakly typed, but PHP7 is strictly typed language with type hinting.
PHP Programs are Not Standalone Programs
PHP is made for Web. Therefore, PHP interact with other systems and external data. Vast majority of PHP is used for Web. It would be rare PHP being used for intensive computation without interacting other systems.
PHP Accepts Arbitrarily Numbers
PHP is used to interact with other system/data, like browsers, databases, JSON, XML, YAML, CSV, TSV, PSV and whatever data programmers have to interact with. External data can be out of PHP and PHP programmer’s control. In fact, it’s out of control in many environment.
Numbers in other system/data are arbitrarily numbers. There are systems uses long digits primary key that cannot be expressed as “signed 32/64 bit integer”. PHP cannot enforce “PHP’s int is signed 32/64 bit integer, so external integer must fit”.
In addition, size of PHP integer changes depending on CPU. This means the same code behaves differently. i.e. 2^31+1 works with 64 bit CPU, raise fatal error with 32 bit CPU.
Correctly written PHP programs handle external numbers as string, thus accept arbitrarily numbers from external when PHP does not have to do any arithmetics. i.e. IDs, Keys, Values that are only passed between PHP and others.
Integer Like Data Can Not Use “int” Type Hint
There are many data that can be converted safely to PHP native integer, year, month, day, age, any numbers between -2^31 and 2^31-1. However, there are many data that can NOT be converted safely to PHP native integer also.
In fact, programmers MUST NOT assume external numbers will fit PHP integer unless they are absolutely sure. Programmer MUST NOT use “int” type hint only because the data looks like integer.
Many PHP developers will use “int” type hint for “integer like string” because it seems working right for small numbers and there is no other type hint for “integer like string”.
Consequence of Improper Type Hinting
Consequence of improper type hinting can be severe. Once number store in external system exceed range of PHP integer, PHP start raising fatal errors. This could result in site/system wide DoS.
Sloppy programmers may find casts as a handy tool to make code work with type hinting. Casts could be evil because it does not raise any errors. It accepts invalid operations without errors.
<?php error_reporting(-1); $o = new StdClass; $a = []; $s = '999999999999999999999999999999999'; // Huge number echo (int)$o; // Raises notice error - Acceptable behavior echo (int)$a; // No error with wrong result (0) echo (int)$s; // No error with wrong result (9223372036854775807 on 64 bit CPU)
Invalid integer casts like array to integer, non-digit string to integer yields 0 (integer zero). Integer zero is often used for special meaning like administrator privilege flag/group/id. Casts may allow attackers privilege to access secret data when it is used improperly.
Basic Type Hinting is Useful or Harmful?
It will be useful for developers who understand what PHP7’s type hinting is doing and it’s limitations. Otherwise, chances are high that it is harmful.
Developers don’t write all of codes needed for a Website today. Developers use many libraries/frameworks/external systems to build a Website. Even if a developer fully understand what basic type hinting is, the developer may be bitten by improper type hint usage.
If libraries with improper type hinting usage are wide spreaded, it will be disaster for PHP community.
What is needed?
PHP accepts arbitrary numbers as string currently. New PHP7 basic type hinting lacks type hint for arbitrary numbers. This is mandatory feature. There are other missing pieces and options. It’s described in previous blog.
Comments are appreciated.
Leave a Comment