views:

89

answers:

6

There are many functions (well most really) in the PHP language that get all upset and throw warnings and notices when they don't like something about their input - rather than just returning FALSE (though they do that too).

One place this is really common is in the GD and string functions. They are very particular about their arguments and it's really easy for user input to fail meeting their standards.

For example, a user uploads a image that is corrupt (intentionally or unintentionally). Resulting in warnings from the GD library.

So far there are only three ways I have found to silence PHP on this issue:

  • Change your error reporting setting in the ini or at runtime (yuck).
  • Suppress errors with the slow @ symbol.
  • Change error reporting right before/after the function:

like so:

$errorlevel=error_reporting();
error_reporting($errorlevel & ~E_NOTICE);
//...code that generates notices
error_reporting($errorlevel);

Naturally, the second two choices just make me sick. Which leaves me using 1) and toning down the PHP error settings. However, I want PHP to be in strict mode so that while I'm working I can catch logic bugs and bad form that might creep into my code. However, I don't want to have random errors thrown when PHP doesn't like something.

So is there any way to separate errors that are from malformed arguments (bad input) from errors that are from bad programming? For example:

  1. If a user image is invalid just return FALSE and I'll deal with it. I don't need warnings.
  2. If my passing of an image resource to print function is invalid throw warnings.
+1  A: 

Fix the code

Sanitize the input before you call the functions. This saves you errors.

Josh K
I am not aware of a way to gauge if an image file is valid until I attempt to open it with GD. If GD can't read it *then I know it's invalid*.
Xeoncross
Xeoncross, in that case, exceptions are needed. Of course, PHP won't help you natively.
erisco
A: 

If there is something like that, you can use the @-operator

Its not a clean solution, but there are situations, where it's indispensable.

Did you check the image before using getimagesize() ?

Dr.Molle
+2  A: 

There's another alternative - use set_error_handler(), you can even call it just before the GD function call and return to the default with restore_error_handler().

There's a good comment in the question try and catch a warning that gives more detail on how this is accomplished.

Clay Hinson
Yes, I actually *used* to do this. However, adding a try {} catch {} block for each function would increase the size of the codebase dramatically. Each 1 line function now = 5 lines of code. Plus it also slow the code down considerably since handling exceptions take more time than just checking `$result === FALSE`
Xeoncross
You don't have to use try/catch for every function, you can use `add_exception_handler()` to set up a default handler for all exceptions.
Clay Hinson
But if I setup a global handler then how do I tie that back to the code I was running when it happened? I have to catch the exception right there in order to deal with it - or else makeup a cumbersome events system that does the same thing.
Xeoncross
+2  A: 

This is an ill-design from the beginnings of PHP. A modern PHP library would throw an exception on error. And an exception may be caught. But back then GD was written PHP didn't yet support exceptions.

Thus I think that in this case it is legitimate to use the @ operator.

nikic
Throwing exceptions would also be ok with me since I can handle them just the same way I would for a boolean FALSE check on the function result. To bad it doesn't throw something that is catchable...
Xeoncross
A: 

However, I don't want to have random errors thrown when PHP doesn't like something.

Why not? PHP is trying to tell you something notable with warnings and notices. In the GD example you'll want to log when a user is uploading a corrupt file - especially if it's being used in an attack. Turn of the display of error messages and log everything.

pygorex1
I think the biggest problem with not catching the errors is the user is thrown to a white or partially loaded screen with no clear explanation on what went wrong or what is going on. For an average user this would be pretty unsettling.
Dan
Klinky
Yes, throwing warning errors is unneeded if you check that the output of a GD function on a user image is `=== FALSE`. At that point you should know something is obviously wrong and log data about the situation yourself.
Xeoncross
+1  A: 

There is no generic approach for all libraries besides editing the offending library and changing how it throws exceptions. Honeslty, a lot of PHP devs really didn't care about exceptions being thrown, but now more and more people are getting on the E_STRICT wagon. When the GD libs were generated the mentality probably was that throwing uncatchable errors wasn't that big a deal.

As far as the validating images with GD. The only thing you can really do is to use a different library or function to validate your images. You might try using magic byte functions to check if the images have proper headers(though this doesn't mean the rest of the file is structured correctly). At least using the magic byte functions will take care of obvious things like someone uploading a text file instead of a JPEG.

Klinky
Perhaps I'm just realizing a design choice that hopefully will change as PHP moves into heavier object-based world. However, I was hoping there might have been a better temporary solution for the time being.
Xeoncross