PHP 4 to PHP 5 - isset checks on boolean if statements - php

Scenario:
We are in the process of converting an application from PHP 4 to PHP 5. The application needs to be able to work on PHP 4 for a little while, which means no PHP 5 specific elements can be used, yet. We are simply trying to make sure the application works on both platforms.
There are a lot of conditionals that look like this in the application:
if ($variable) { // do something }
Some of these variables end up not being defined at all and we are trying to reduce the number of errors (there's a lot of them).
To solve these errors, we are adding checks in various areas like this:
if (!isset($variable)) $variable = "";
or
if (!empty($variable)) { // do something }
Question:
Does anyone know of a simpler approach to fixing these errors. The problem is that these variables are being used across files (via includes) and defining the variable may change the logical flow in that file if its doing a check like (if (!isset($variable)) { // do something }).
The point of this question is to reduce errors and time consumption of tracking each individual use of these variables. Currently, we are having to either examine thoroughly what the variable is doing (which may take a good chunk of time), or we are doing a "fire and forget" / hope-its-fixed method of correcting.
-- Edit --
Does anyone know of a program like cppcheck for php that could somehow reference these variables or create some kind of chaining that could find errors and link possible references? (I hope that makes sense.)

AFAIK there is a code-checker that looks for uninitialized variables which works OK. You can work through it's messages, it's called PHP Mess Detector and one of it's rule covers uninitialized variables. However this can never be perfect.
Another method is to track the error messages and use them to locate the places within in the code. I've done that in the past and it worked very well, just do it in iterations and keep log of the warnings.
You can also work with a whitelist and import whitelisted variables when the request starts. Non-whitelisted submissions need to cause an access violation error to have this properly working, so this way is more work than tracking warnings albeit it might make your application more secure.
Please see as well:
PHP Syntax checking pre-source control
E_NOTICE ?== E_DEBUG, avoiding isset() and # with more sophisticated error_handler
isset() and empty() make code ugly

Related

"Do not Access Superglobal $_REQUEST Array Directly." Netbeans 8.0 PHP

This questions is being asked after having read a few others.
Do not access superglobal $_GET array directly
“Do not Access Superglobal $_SERVER Array Directly” on Netbeans 7.4 for PHP
Why is filter_input() incomplete?
I have loaded up the latest version Netbeans 8.0 and I have seen a warning
Do not Access Superglobal $_REQUEST Array Directly.
Great, I am happy to be shown when I am doing something which can be improved upon, so I look at the hints.
The suggestion is quite simple.
Use some filtering functions instead (e.g. filter_input(), conditions
with is_*() functions, etc.).
So I start looking into fliter_input() however it is not yet implemented for $_REQUEST. This seems like a little bit of a dead end.
Then I read something which was quite helpful from (#bobince) "At the start of your script when you're filtering, you don't know where your input is going to end up, so you don't know how to escape it."
It reminded me, I know exactly where my input is going to end up, and exactly what it will be used for. So, I wanted to ask everyone if the approach I am going to take is essentially safe.
I am designing a REST-ish API and I am using $_SERVER['REQUEST_METHOD']; to determine the resource which needs to be returned. I am also using $_REQUEST['resource']; which should contain everything on the URI after /api/ following the .htaccess rewrite.
The questions I have about my approach are:
If I always validate $_SERVER['REQUEST_METHOD']; to be within the required GET PUT POST DELETE (which i will need to do anyway), is there really a problem not filteing the input?
Should I be accessing the $_REQUEST['resource']; by using filter_input (INPUT_GET, 'resource');? When this will only be used to determine a resource, and where the resource can not be determined (say someone attempts to add malicious code) we will simply not find a resource and return a 404 Not Found status.
Are there any other considerations I need to take into account and have I missed anything critical in my understanding?
I realise, this may seem like a lot of concern for what is only considered a warning however, in my experience, fixing just the errors will give you working code, but fixing the warnings will help you understand why the code works.
So I start looking into fliter_input() however it is not yet implemented for $_REQUEST. This seems like a little bit of a dead end.
I'd say it is not a dead end but on purpose. filter_input() requires you to clearly specify the input type. $_REQUEST is not clear about it, it contains input from various sources, allowing one source overwriting another.
Next to that this is also not what the warning precisely wants to tell you. Swapping a superglobal like $_GET with an equally superglobal function like filter_input(INPUT_GET, ...) shows the same design flaw. But Netbeans can't warn you as easily about it.
And getting rid of superglobals is already a good idea.
Instead, inject input data to your application at a low-level place, e.g. bootstrapping the request information and do not use any superglobals nor the filter_input function in the rest of your code.
That will allow you to easily simulate any request method without even having an actual request.

How to break on variable change in PHP?

Is there any way to break on variable getting changed?
E.g. Variable $abc is used and modified in many different functions and files, when I debug a large project, I want to know when it get changed exactly.
Setting breakpoints can only tell me what the value is at that point, but I want to know the whole life of this variable.
Please search for 'php debugger'.
But I don't use one. It's relatively easy to search your source base for that variable and then use var_dump()'s to display when a variable is it's getting changed. Do you know how to use the Search all files feature in Notepad++?
Then once you've found your problem, use the undo to restore the files, and take the var_dumps() back out.
I also often put a die in places to stop so I can know for sure where a particular var_dump is executing.
I keep a Debug variable in my ini file and have a way to easily turn it on and off, and then can watch certain variables with if($ini['Debug']) var_dump($myvar);
There are some advantages to doing things this way rather than with a debugger. First your code runs faster, and this can matter depending on the complexity of your code. Second, it always works, no matter how strange your code, whereas there are sometimes things that can fool a debugger.

Simulated Ruby symbols in PHP

Ruby and some other languages have a very convenient feature: symbols. They look like in-place constants. Now I wonder if the following approach by simulating symbols in PHP with an at sign before an unquoted string is a valid approach.
$array = [#key => "value"];
echo sprintf("%s PHP symbols with a %s\n", #testing, $array[#key]);
I understand there are certain drawbacks against formal constants and the like, which are same as for Ruby's symbols: consider typing errors. Are there any other considerations against using this approach?
If by "valid" you mean "can be run", then yes, it is a valid approach (but by that standard, it is also valid to make all of your strings into HEREDOC's). But simply because PHP will accept the syntax, does not mean that the syntax is without problems.
The first I can think of are that
You are actively suppressing an error, which costs processing time
Your co-workers will need an explanation as to what is going on, which costs developer time
You are working against the natural definitions of the language (PHP simply isn't Ruby)
Since you have to use a sigil for variables anyway, you're not actually cleaning the code.
You are suppressing an error (a notice, to be exact). not only this costs processing time as mentioned in cwallenpoole's answer, but also the error is there for a reason. The reason is:
Notice: Use of undefined constant hello - assumed 'hello' in ...
You are relying on some constant being undefined - which is exactly what the notice is trying to tell you. If a constant of that name is defined, you will grab its value instead.
In Ruby, :__LINE__ is something quite different from __LINE__. The former is a symbol - it equals itself no matter where you use it. The latter is a number, and a magical variable that changes its value on every line. In PHP, #__LINE__ is the same as __LINE__, because there is no error to suppress. Oh, and there's one special "symbol" that is extra-fun to debug: #exit, AKA #die.
In Ruby, you can use all sorts of symbols including operators and keywords. These (and many more) are all valid: :+ :* :< :<< :[] :[]= :while :case :x=. With a pair of parentheses, you can even use symbols like :case= and :while=. In PHP, none of these work. You'll end up with a parse error. It won't even be suppressed. The only exception is #[] in PHP 5.4, which produces an empty array. On the other hand, lots of PHP expressions are not valid Ruby symbols: #(1+1) === #2 #1 == #'1'
Ruby's symbols are not equal to anything else. This is the purpose of their existence. Sure, they have some nice properites like to_s and to_proc, but their original purpose is to serve as identifiers separate from any possible user input. This is sorta nice for example if you are using symbols to represent tokens in a lexer stream, such as [:lparen, 1, :plus, "rparen", :rparen]. In PHP, undefined constants are strings. In Ruby, ?test != "test". In PHP #test === "test" (assuming you dindn't define a constant named "test" to equal something else).
you can't even assume non-magic constants won't change. You can't even attribute to malice what can be explained with bad coding. Nothing like that is of worry in Ruby:
//in library code:
$this->status = #done; // bad
//outside library code:
define('done', "no"); // very bad
define(#done, "yes"); // even worse
echo #no; // prints "yes"
//in library code:
if($this->status == #done){
//won't execute
}
echo #die;
echo "this won't get printed!";
You shouldn't rely on constants being undefined, and you shouldn't use error suppressing to hide the error messages telling you that. You shouldn't use special notation to pretend two things are not equal when they are. Also, can you trust the users of your library to not redefine constants at runtime?
Warning:
The following answer contains analogies that are meant, purely to illustrate a point. Under no circumstances do I mean to even suggest you contemplate the possibility of someone (you or anyone else) actually sitting down and doing the things I mention. That way madness lies
Though other answers have explained the main issue with using #<str>, It supressing a notice, it's important to stress this a bit more.
When using the supressing # (of death) the notice does not magically dissapear it is still being issued. After a while logs will get clogged with notices, making it harder to find that one fatal error that could be in there. Even if there is no fatal error, it still slows the code down.
Why encourage people to write code that throws notices? Just because you like the ruby syntax? come on, if you don't like a language, don't use it. I know: legacy code, you have to... well then, do it, don't try to make it feel and look like Ruby. They're not the same language. Everything that reminds you of the fact that you're working with a different language should be seen like a tool. Different languages require different mindsets, and different ways of thinking about a problem.
Imagine writing Lisp, but change the syntax to SQL queries. How much bad code will that generate. The syntax forces you into an SQL mindset, whereas you should be thinking in functions.
But for God's sake, don't that way madness lies!! It's a fools errand, it's even worse than parsing HTML with regex. It'll make even Cthulhu cry like a little girl
Oh, and # not being used to supress errors once it's in common usage? Do you really believe that? So you expect a lot of people to write bad code, until some IDE plugin is released that doesn't complain about the abuse of the # sign. And then, you expect the PHP contributors to take notice, and find a new operator to supress errors?
Honestly. I don't want to be rude, but that's like expecting Microsoft to release the source of windows8, because some people have gotten used to linux being open source.
Another thing: As I said, suppressing notices isn't going to help you when debugging the code. It's well known that PHP has way to many functions (and reserved keywords) in its core/global namespace. If you, and your co-workers get in the habit of abusing the # operator, you could just end up with code like this:
$foo[#die] = [#exit, #constant];
Have fun debugging that onholy mess of unclear errors. Honestly...
The key in your code would be seen by PHP as an unknown constant.
In most languages this would halt the compiler, but PHP mutates it into a string in an effort to keep running. It throws a warning, but keeps going anyway. This is just bad, and you really don't want to be doing it, much less doing it deliberately.
# in PHP is for suppressing errors. It does nothing else.
Your #key will still be bad practice just as key would be and would function in exactly the same way, but the # will hide the error message that would normally be generated.
Using # error suppression in PHP is bad practice for a whole bunch of reasons (‡ see note below), but using it as a way to hide deliberately bad code is terrible. Please don't do this.
The fundamental point here is that you're using PHP, so you should write PHP code. Trying to write Ruby code in PHP is never going to work.
You should work with the language you're using, not against it.
‡ For some thoughts on why error suppression is bad practice, you may want to read this: Suppress error with # operator in PHP
One final thought: This thing of PHP converting unknown constants to a string exists in the language purely for legacy compatibility reasons; it's one of the really awful bits of bad language design that date back to the early days. A lot of the other bad stuff from early PHP has been deprecated in recent versions; this hasn't yet, but there's no good reason for it still to exist, so I kinda hope they find a way to deprecate this "feature" too. If they do, that will instantly stop your idea from working, regardless of any merits it may have.

PHP: if ($Name=='ProxiedIP') leads to 500 (Internal Server Error)

This may be too obscure of an question, but I've been troubleshooting a baffling server error for hours and have pinned it down to the most bizarre issue; at this point I just want to know if anyone has ever had something similar occur, or might have any insight into what might possibly be happening.
The following line of code is triggering the error:
if ($Name=='ProxiedIP') { return true; }
This version runs without any problem at all:
if ($Name=='proxiedIP') { return true; }
It seems like somehow the token 'ProxiedIP' is fouling something up, but I cannot even think of how a string literal would be translated by the parser in a way that could hang the server up like this. BTW, I know for certain that $Name!='proxiedIP' and $Name!='ProxiedIP'.
Here's the entry in the apache error log:
[Fri Jan 18 18:15:12.924419 2013] [core:error] [pid 27676:tid 3427232831232] [client 12.345.67.890:34482] Premature end of script headers: index.php, referer: http://mySite.com/
I searched for 'ProxiedIP' as a keyword for every component that I can think of on my system and I'm coming up with nothing. The more imperative question for me though is how a string could somehow have this impact in a comparison check. Any ideas?
Also noteworthy that the PHP error log is completely silent about it. I'm enabling error output at the top of the page, but the script never finishes loading so that may be a factor. Here's how I'm setting it:
error_reporting(E_ALL);
ini_set('display_errors', 1);
Because the code worked here, it seems more likely that it could be something specific to the platform implementation. I'm running this on an instance of Gandi.net's 'Simple Hosting' service, which runs Varnish for application acceleration. It may also be worth mentioning that the code is being loaded in an iframe in a separate domain.
I am also doing some intensive work with the headers, and this seems like the greatest potential source of the problem, although the strange thing as far as I'm concerned is the way the error is being triggered. Also, there's no common header that I'm aware of called 'ProxiedIP', although that use conflict is the only thing that seems like it could make sense so far. Regardless, I don't see it.
To me, the real item of relevance is the mere fact that a string comparison is crashing the server. I've been programming in PHP for over 10 years and I have never had anything like this happen before. I'm trying to understand the logistics behind how it could even happen.
Update: I've tried the following variation, and it still produces the same result:
if ($Name === (strtoupper("p").'roxiedIP')) { return true; }
It was asked whether I would post the full code, but the script for the iframe side is 1400+ lines long so that's not really feasible. I'm adapting the segment in question to try running it in a new script though and will post the results.
I think the problem is with the variable $Name. Check whether it is getting assigned properly. Also check the code after if statement which is causing the problem.
Actually, I think your problem lies in the calling function, i.e. depending on the return value it does something "stupid" and PHP crashes.
Try replacing the if() with a hard return true or return false and see what happens.
As i get from your error, you are messing up the framework, the change in that if of yours triggers some output being called before the fw is allowed to make output. Just read it in more detail, you got it on the wrong train, that is not the cause of the error, it is the beginning of an unhallowed state of the fw.
Try running the script in a php debugger rather then using var dump.
Thanks for the posts, but it turned out to be a really convoluted scenario, where conditions several levels down the function chain caused unexpected behavior outside the scope of either function in question.
The actual issue was due to a condition check while parsing through output of a debug_backtrace() array in a totally separate process, which ironically was in place to prevent infinite recursion and instead triggered a similarly disruptive cascade of events that overran the allocated memory limit.
I originally posted because I was baffled by what truly seemed to be a string literal comparison doing something I didn't think should be possible, and wanted to understand what conditions could allow it to happen if so. I'm just glad the cause wasn't actually what it seemed to be. Thanks for helping to solve the puzzle.
Update: The true source of the error hinges on PHP's difficulty translating objects or arrays that contain references to themselves. I'm storing converted headers, direct header references, $_REQUEST[] and $_SERVER[] items, as well as logging messages and associated data in complex associative arrays. There are a lot of dynamic references between these items, particularly those involving the native PHP globals which I've made use of.
PHP has traditionally had problems managing self-referencing entities, and although improvements have been made, my particular situation is complex enough to send ReflectionClass into an endless loop while attempting to map these objects. I've fixed it by manually dereferencing the items as I'm polling them, but it's something to be aware of if needing to work with multiple $GLOBALS-related vars within a common array or referencing structure.

How to get $_GET variables in PHP

I'm working on application built years ago, that has recently stopped working correctly. Old programmer said, that he might be accessing $_GET or $_POST variables without reading them from $_GET[] array, but through the register_globals
I want to ask: What are different ways to access $_GET variables without using $_GET[] array (e.g. direct ways?) and, if known, how can I check if this application uses any of them?
Thank you in advance
EDIT: The other ways I remembered was register_globals, not magic_quotes. Also, I do not wish to use it, but rather detect if it was used and in latest server update deprecated (what could explain why app stopped working correctly)
EDIT: My english is horrible today. As I explained in one of answers: I need to check, whether original programmer used some obscure and/or deprecated method of getting variables from query string to PHP, so the values application now works with are wrong/not initialized
IMPORTANT EDIT: import_request_variables is off the table, it isn't used. All $_ arrays are off the table too, because latest update wouldn't broke them (=>they still work). How can I detect what variables are initialized with register_globals?
YET ANOTHER EDIT: I found this:
foreach ($_POST as $k => $v) {
eval("\$".$k." = '".$v."';");
}
foreach ($_GET as $k => $v) {
eval("\$".$k." = '".$v."';");
}
Could it have been broken by one of latest updates (max. 1 week ago)?
You mean through Register Globals and not Magic Quotes... BTW Register Globals is pure evil never use them (and they are deprecated as of PHP 5.3.0)!
Edit: If you want to check if the application used Register Globals, try to search for $_GET values as variables. For example for index.php?id=123 try to look for $id in the PHP code. If you find it this does not mean that the script uses Register Globals but if $id comes from nowhere and is never initialized/setted it's a good (bad!) sign that the app uses Register Globals...
$_SERVER["QUERY_STRING"] will give you the raw GET string.
That said, this sounds like a problem that should be fixed at its root, not by using a different variable.
If magic quotes are an issue, do a check for whether they are enabled, and deal with the incoming data accordingly.
The Disabling Magic Quotes page in the PHP manual shows a way to "fix" the incoming data depending on whether the functionality is activated or not. It's not very efficient for huge amounts of data, but should do in an everyday task.
You also have $_REQUEST, magic_quotes (deprecated) would only influence the content of the variables, not the means of capturing them.
Also see import_request_variables, the original coder may have used it to grab the contents of a GET variable and insert it into another variable which is then subsequently being referenced.
Register Globals is a horrible feature that older PHP programs often rely on.
With register globals switched on, PHP will look at the GET and POST variables and "promote" them to normal variable names - eg $_GET['myvar'] would be accessible in the code as $myvar.
Among other issues, this makes the program very easy for hackers to break simply by guessing what other variable names the programmer may have used. The register globals feature has therefore been turned off by default for a long time, is now officially deprecated, and will be removed entirely in a future version.
Because the variables used this way are referenced in a way that is indistinguishable from normal variables, it means that trying to update old code that uses register globals can be very difficult. It does depend a lot on how well written the code is.
The problem is probably PHP's register_globals. This option makes $_GET['some_var'] or their equivalent $_POST version available as $some_var automatically. This is deprecated and you should definitely not use it, but the other programmer might have used them in that application.

Categories