Force PHP integer overflow
So I solved the problem, and discovered a lot about PHP (at least in the way it handles Integer overflow).
1) It completely depended on a cross between which platform the machine was running on, which version of PHP, whether or not it had Suhosin Hardened PHP running, and how many bits it was compiled for (32 or 64). 6 machines behaved the way I expected (which was actually wrong, at least wrong according to their documentation) and 3 machines behaved in a way I still can't explain, and 3 machines behaved according to what the intval command says it does in the documentation.
2) Intval is supposed to return PHP_INT_MAX when int > PHP_INT_MAX (not int & 0xffffffff), but this only happens on some versions of PHP4 and PHP5. Different versions of PHP return different values when int > PHP_INT_MAX.
3) The following code can return 3 different results (see 1):
<?php
echo "Php max int: ".PHP_INT_MAX."\n";
echo "The Val: ".(-1580033017 + -2072974554)."\n";
echo "Intval of the val: ".intval(-3653007571)."\n";
echo "And 0xffffffff of the val: ".(-3653007571 & 0xffffffff)."\n";
?>
It can return (which appears to be right for Intval but wrong for & 0xffffff)
Php max int: 2147483647
The Val: -3653007571
Intval of the val: -2147483648
And of the val: -2147483648
And it can return (which contradicts the PHP documentation for intval):
Php max int: 2147483647
The Val: -3653007571
Intval of the val: -641959725
And of the val: -641959725
And on 64 Bit machines it returns (which is correct):
Php max int: 2147483647
The Val: -3653007571
Intval of the val: -3653007571
And of the val: -641959725
Solution
Anyhow, I needed a solution that would work on all these platforms, and not be dependent upon quirks of a particular version of PHP compiled with a particular Max int. Thus I cam up with the following cross-PHP thirtyTwoBitIntval function:
function thirtyTwoBitIntval($value)
{
if ($value < -2147483648)
{
return -(-($value) & 0xffffffff);
}
elseif ($value > 2147483647)
{
return ($value & 0xffffffff);
}
return $value;
}
Comment
I do think the designers of PHP should have said an Int is a 32 Bit Int no matter whether it is running on a 32 or 64 or 128 bit machine (like the DotNet CLR for example), and didn't randomly upconvert it to a float depending on the number of Bits that PHP is compiler under.
Testing integer overflow in PHP
Use the PHP_INT_MAX
constant:
$this->assertEquals( PHP_INT_MAX, $text );
This will fix your problem, AND make your test more portable (e.g. it will work on 32bit systems too).
PHP_INT_MAX's value is the larger representable int
by your PHP build.
See http://php.net/manual/en/reserved.constants.php
PHP: how to force property of method to be integer?
You can't force strict types in function prototypes in PHP inherently, because it's not a strictly typed language. PHP is a weakly typed language and trying to go against the grain will only hurt you in many situations. Also, is_numeric does not guarantee that your value is of type int (for what it's worth).
What you can do is analyze your need for why you think this approach is necessary in the first place and decide on how to best implement this without creating potential for bugs.
For example, take the following scenario where what your method expects is an ID for a database query.
class MyClass {
public function getUser($id) {
if (!is_int($id)) {
throw new Exception("Invalid argument supplied. Expecting (int), but argument is of type (" . gettype($id) . ").");
}
// Otherwise continue
$db = new PDO($dsn);
$stmt = $db->prepare("SELECT username FROM users WHERE user_id = ?");
$stmt->execute(array($id));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
$MyObject = new MyClass;
$result = $MyObject->getUser($_POST['id']);
/* The problem here is $_POST will always be of type string. */
What this should tell you is that it makes no sense to force type checking here since PHP will have done the right thing for you had you just let it alone.
The question you need to be asking yourself is not "How do I force strict typing?", but rather "Why would I need to force strict typing at all?".
PHP - Force integer conversion to float with three decimals
Try using sprintf()
$numbers2[] = sprintf("%+07.3f", $fnum);
How to force arguments to be integer/string
Scalar TypeHints are available as of PHP 7:
Scalar type declarations come in two flavours: coercive (default) and strict. The following types for parameters can now be enforced (either coercively or strictly): strings (string), integers (int), floating-point numbers (float), and booleans (bool). They augment the other types introduced in PHP 5: class names, interfaces, array and callable.
There is no Type Hints for scalars before PHP7. PHP 5.3.99 did have scalar typehints but it wasn't finalised at that point if they stay and how they will work then.
Nevertheless, there is options for enforcing scalar arguments before PHP7.
There is a couple of is_*
functions that let you do that, e.g.
is_int
— Find whether the type of a variable is integeris_string
— Find whether the type of a variable is string- more
To raise a Warning, you'd use
trigger_error
— Generates a user-level error/warning/notice message
with an E_USER_WARNING
for $errorType
.
Example
function setInteger($integer)
{
if (FALSE === is_int($integer)) {
trigger_error('setInteger expected Argument 1 to be Integer', E_USER_WARNING);
}
// do something with $integer
}
Alternative
If you want to use Scalar Type Hints desperately, have a look at
- http://edorian.github.io/2010-03-30-typehints-hack-for-literal-values-in-php/
which shows a technique for enforcing scalar typehints via a custom Error Handler.
PHP String-to-Integer Exception
And here's another hacky solution using the try {..} catch mechanism:
try {
new ReflectionClass('ReflectionClass' . ((int)$SS . "" !== $SS));
echo $SS;
} catch (Exception $e) {
echo "Bad StringBad String";
}
It works like this: if the string $SS
doesn't actually resolve to an integer, the code will try to lookup the ReflectionClass1 class, which, in the end, will throw a ReflectionException
.
The parsing works by simply casting $SS
to int
and then back to string and comparing it to the initial value.
Related Topics
How to Return a Value from a Form in C#
Configure the Authorization Server Endpoint
Is There Any Benefit to This Switch/Pattern Matching Idea
How to Force All Referenced Assemblies to Be Loaded into the App Domain
Linq to Entities Does Not Recognize the Method Last. Really
Differencebetween "X Is Null" and "X == Null"
How to Customize the System Menu of a Windows Form
What Does $ Mean Before a String
Is Ruby's Code Block Same as C#'s Lambda Expression
Difference Between "\N" and Environment.Newline
Change C# Dllimport Target Code Depending on X64/X86