Accidental error in setting php_value in .htaccess? - php

So when I currently view phpinfo() in PHP, my error_reporting is set to some number, which represents the sum of all the error constant values, right?
Let's say, I accidentally set the value of error_reporting to some weird value by accident in .htaccess for example:
-1
Value that is bigger than E_ALL (32768 for example, if I'm correct)
When setting it with a string, I do a typo (**E_AL** & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED) - typo in E_ALL
What would happen, would it be set to some default value? Or from php.ini? I tried setting all the values above and they all were set in the Local Value without any problems.
I'm curious what will happen with any other value as well, will it default to php.ini or what?
Thanks!

PHP uses bitwise operators to determine whether the error level should be reported.. so whatever your integers value is as binary it would bitwise & to see if the error is reported.
E.g.
if E_DEPRECATED were (not saying this is accurate): 01, E_WARNING is 10, E_NOTICE is 100, using E_DEPRECATED | E_WARNING | E_NOTICE would give the binary 111, thus when an error is reported, like E_WARNING, it would take the value set, and bitwise & it to determine whether the report is displayed:
111 & 010 = True, so the error would be reported.
if you just used E_DEPRECATED | E_NOTICE, the binary is 101, so 101 & 010 = False, so the error won't be reported.
Each of these binaries can be converted to base10, 01 = 1, 10 = 2, 100 = 4 etc.
So if you were curious as to which errors would be reported with your random integer you can do:
int & E_WARNING in your PHP parser, if its True then the error will be shown, if its FALSE then the error will be ignored.
This is a good convention to learn, as its very useful when implementing logging on your application too, you can use the same system, and so you don't have to implement a long switch or if .. elseif .. block to determine whether a log level should be logged or not according to config.
/**
* Determines whether this message should be logged based on the provided type and the set threshold
* #access protected
* #param int $type
* #param string $name name of the log to check.
* #return boolean
*/
protected function should_log($type,$name='default') {
return (bool) ($this->getConfig($name)->threshold & $type);
}
so the threshold would be a binary number in your config (which uses constants for readability) then it bitwises & against the provided log type which returns True or False to determine whether to log the message to the logger by name $name... much more optimised.

Related

Why do you have to do a binary operation in error_reporting?

It may sounds like a stupid question, but there is something I don't understand about error_reporting and I could not find the explanation on php.net or after a research on google.
My local workstation error is this :
error_reporting(E_ALL - E_DEPRECATED - E_WARNING);
Everyone else at work is :
error_reporting(E_ALL & ~E_DEPRECATED & ~E_WARNING);
My question is : why does it give the same result ? And why do you have to use a binary operation and not a simple substraction?
Thank you in advance.
Because E_DEPRECATED and E_WARNING have completly different bits set and you substract them from E_ALL were all bits are set.
The real difference occurs, if you try to remove two times the same bitset or combined bitsets. In this case, you would remove the 'bits' more than once, which leads to completely wrong values.
In general, you would probably just remove a single option from the error flags and don't know, which bits are currently set
$level = error_reporting();
// at this point, you simply can't use simple math, as you don't know, if the given error reporting option is set or not
$level = $level & ~E_WARNING;
error_reporting($level);

Function parameters of the form foo(A | B | C)

This is a language-independent question, though I've tagged with languages just to give some tags relevant to the code samples I'm posting below. I'm somewhat new to programming. In various languages I've seen functions that have parameters separated by what I think is the bitwise OR operator. I've used these functions without understanding exactly how the parameters work.
I'll give some examples in case you're not sure what I'm talking about.
From http://www.php.net/manual/en/function.error-reporting.php:
<?php
// Turn off all error reporting
error_reporting(0);
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
?>
From http://www.cplusplus.com/doc/tutorial/files/:
ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);
What exactly is the deal with functions that take parameters like that? Can someone explain?
If you lookup what those constants are, you'll see they'll be like this: 1, 2, 4, 8, 16, etc.
So by adding them all together basically, (what the bitwise does AFAIK from this: "Bit shifting in PHP is arithmetic.") you get a new "number".
http://us2.php.net/manual/en/language.operators.bitwise.php
The manual page has a lot of good info on how it works.
So basically to answer the question of how that function works, it is accepting one integer, and the bitwise operator is doing the "math" and turning those three constants into one new number.
var_dump(E_ERROR);
var_dump(E_WARNING);
var_dump(E_PARSE);
var_dump(E_ERROR | E_WARNING | E_PARSE);
int(1)
int(2)
int(4)
int(7)
So it's the same as:
error_reporting(7);
The same thing as a + b + c. It's just an expression, with
the | (bitwise or) operator.
These are predefined constants, whose values are combined to produce a bit field.
You can use decbin() in PHP to give an insight into how these constants work. decbin produces a string which shows the binary representation of the number.
printf("%02s", decbin(E_ERROR)); // output 01
printf("%02s", decbin(E_WARNING)); // output 10
printf("%02s", decbin(E_ERROR | E_WARNING)); // output 11
(I padded all the values so that the OR operation is clear)
You're passing a single number to the function, whose value represents the options you want to enable. In the function, the options could be extracted using bitwise &:
function func($flag) {
if ($flag & E_ERROR) echo "E_ERROR enabled";
// etc.
}
These are flags. Sometimes a function receives multiple indications on how to operate, such as whether to open the file in binary mode, or in read-only mode, etc... This modes are not mutually exclusive - file can be opened for reading in both text and binary mode, or for writing in both text and binary mode. So you need to be able to specify both options together if you want.
One simple way to achieve this is with bit flags. You have one integer number that holds all the flags. The least significant bit says, for example, if the file is to be opened in text mode (0 - text, 1 - binary), the second bit from the right says whether to open for read or write, etc...
To implement this you use constants:
BINARY = 1
WRITE = 2
Now, if you want to open in both binary and write mode, you use BINARY | WRITE - which results in 3.
The called function then breaks the number back into bits:
isBinary = (flags & BINARY) != 0;
isWriteMode = (flags % WRITE) != 0;
I think
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
is equivalent to the following in C or C++
// Report simple running errors
int const error_filter = E_ERROR | E_WARNING | E_PARSE;
error_reporting( error_filter );
Most probably, the symbols E_ERROR, E_WARNING are numbers with a single bit set, such as for example
E_ERROR = 00000001
E_WARNING = 00000010
E_PARSE = 00000100
So, a bitwise-OR of them returns a number with the bit set in all of those positions
error_filter = E_ERROR | E_WARNING | E_PARSE = 00000111
One tricky thing is the type of error_filter, I wrote int but that may not be pedantically correct. One can say uint32_t. Another alternative is to leave the type altogether as in the original code.

Binary operation to get / set property

I would like to store user rights as integer in database, but not sure how... How does it work on PHP with for example error_reporting() ?
You got different constants, like... E_ERROR = 1, E_WARNING = 2, E_PARSE = 4, E_NOTICE = 8 etc... and you can set it like error_reporting(E_ERROR | E_NOTICE) ...
In this case E_WARNING | E_NOTICE == 10.
Ok, so I do understand that this is binary operation "OR" and as far as consecutive constants are multiplied by 2, everything should be reversable... but how?
So I got this (int)10. And how do I check that it is E_WARNING and E_NOTICE?
PS. I do understand that it is 1010 on binary notation.
If you want to check if values are set, you can use the bitwise AND & operator.
$warningEnabled = $val & E_WARNING;
This works because (assume $val is 128)...
1000 0000 & # $value
0000 0010 # E_WARNING
Since the same bit isn't set in both, you can tell that $val doesn't have warnings set.
You can execute this in PHP if you like with bindec() function (wrap the above values as strings), it may help you understand better.
If you want to know if the value contains E_WARNING, do:
if ($value & E_WARNING)

bitwise operators

I would like to understand the following code from Zenphoto’s plugin:
$plugin_is_filter = 5|ADMIN_PLUGIN|THEME_PLUGIN;
The snippet was disjointed from context. It is just about the Idea behind it.
Are 5|ADMIN_PLUGIN|THEME_PLUGIN Permissions using bitwise?
When it is useful to use?
Thanks for any hint, links.
Bitfields are useful when you need to provide a set of boolean options in one variable. For example, PHP lets you set your error reporting like this:
error_reporting(E_ERROR | E_WARNING | E_PARSE);
In binary, those constants have these values:
E_ERROR 0001
E_WARNING 0010
E_PARSE 0100
If you OR a set of options like that together, you'll be able to express the settings in one field:
E_ERROR | E_WARNING | E_PARSE 0111
Then, you can check for an option being set using AND:
if ($option & E_ERROR === E_ERROR) {
// E_ERROR is set, do something
}
Yes, that is an example of bitwise OR.
You typically use bitwise operations when you're interested in packing multiple boolean flags into a single integer. Bitwise operators allow you to manipulate the individual bits of a byte, meaning an 8 bit byte can be used to store 8 distinct boolean values. It's a technique which was useful when using a whole 8 bit byte to store a single binary "yes" or "no" was considered wasteful.
Today, there is virtually no reason to ever prefer using this kind of bitpacking in PHP (especially with a magic number like that 5) over a simple configuration array. It is a technique which adds virtually nothing of value to PHP code, increasing complexity and decreasing maintainability for no real gain. I would be very skeptical of any new PHP code produced which makes use of bitwise flags in this way.
The variable $plugin_is_filter is being used to flag which plugins to load. Essentially, it is being treated like an array bits that correspond to an enumerated set plugins. For more information, see the links below.
This explains what ADMIN_PLUGIN and THEME_PLUGIN are.
Search the page for '$plugin_is_filter' to get a brief explanation of how to use this variable.
http://www.zenphoto.org/news/zenphoto-plugin-architecture
I hope this helps.

Is it possible to log the entire value of parameters in Exception traces?

When reading over my error logs I notice that long parameters (such as SQL strings) are truncated in the Exception trace. Here's an example:
FR_Model.php(204): FR_Base->query('INSERT INTO pos...', Array)
I'd like an easy way to echo the full parameter without having to roll my own Exception subclass. TIA.
Check your log_errors_max_len PHP setting. From php.net:
log_errors_max_len integer - changeable: PHP_INI_ALL
Set the
maximum length of log_errors in bytes.
In error_log information about the
source is added. The default is 1024
and 0 allows to not apply any maximum
length at all. This length is applied
to logged errors, displayed errors and
also to $php_errormsg.
To test: (via this Bogus bug)
<?php
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors',0);
ini_set('log_errors',1);
ini_set('log_errors_max_len','0'); //change this value
ini_set('html_errors',0);
function deepTrace($a, $b, $c) {
if ($c < 50) {deepTrace($a, $b, $c+1);} else {throw new Exception('Example exception that together with the trace is over 1024 bytes.');}
}
deepTrace('example','function',0);
?>
If changing log_errors_max_len in this sample code to 0 doesn't work, but changing it to a number larger than 1024 has some effect, then you are almost certainly loading a zend_extension somewhere that is overriding PHP's standard behavior, such as Zend Optimizer, Zend Debugger, Xdebug, etc.
Try grep -r zend_extension /etc/php.* to locate any extensions in use; if it finds a matching line that isn't commented out, there's your culprit.

Categories