note 36191 rejected from function.fgets by didou

From: Date: Tue, 30 Sep 2003 07:40:35 +0000
Subject: note 36191 rejected from function.fgets by didou
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-57377@lists.php.net to get a copy of this message
Note Submitter: jbayman@hobbithell.com ---- According to the documentation, fgets will return either a string or FALSE on error... However, this is NOT true and applies for almost all stream functions (list of known functions affected at bottom of post). The problem is, when a PHP function opens a stream, it uses "php_stream_from_zval" call to open it. This is a macro for "ZEND_FETCH_RESOURCE2" which in turn is another macro which calls "zend_fetch_resource" and then checks the return code using the macro "ZEND_VERIFY_RESOURCE" which will call "RETURN_NULL();" if "zend_fetch_resource" failed. In C/C++ (which it is coded in C) a macro is a piece of code which is inserted where the macro is called at compile time. What that means is, it effectively changes the definition of fgets to include this code which will cause fgets to return NULL if the resource cannot be opened. Long story short, ANY function (list of known functions affected at bottom of post) calling on "ZEND_FETCH_RESOURCE" or "ZEND_FETCH_RESOURCE2" (and possibly others as well) WILL return NULL if it is unable to open the resource. This includes basically ALL of the stream functions as possibly others. So this post applies to a LOT of functions in which the documentation fails to inform you that it may return NULL if the resource was unable to be opened. (Note: a resource here is referring to it's HANDLE. As such, it means that only functions requiring a resource handle are affected by this, not functions like fopen which return a resource handle) This mainly happens when you open a resource and fail to check to make sure it returns a valid handle to the resource. So in short, make sure you check your results from functions such as fgets for both FALSE as well as NULL. To demonstrate: // fsockopen returns int on success and bool(FALSE) on failure $fp = fsockopen("127.0.0.1", 110); if(is_bool($fp)) { // fsockopen failed exit(); } // fgets returns string on success, bool(FALSE) on failure, // and NULL if an invalid resource handle was supplied // Note: This will cause an error to be outputted if you // have displaying errors enabled under PHP $result = fgets($fp); if(is_bool($fp) || is_null($fp)) { // fgets failed - fsockopen probably returned FALSE // and you didn't verify that... SHAME on you! fclose($fp); exit(); } While this could technically be considered a bug, it is actually not significant, not to mention can be easily avoided by asserting that you pass it a valid resource handle. It seems it's more of a documentation error, however... If the functions were to use "php_stream_from_zval_no_verify" and test "xstr" (argument 1 of php_stream_from_zval_no_verify) and return FALSE instead of NULL on that error, then the current documentation would be correct... Question is, is it really a bug or was it the intention of the programmer? After careful examination of all code, it would appear to be more of the intention rather then a bug. This is true for all releases of PHP up to September 30th, 2003, including PHP Version 5.0.0b1 "ZEND_VERIFY_RESOURCE" and "ZEND_FETCH_RESOURCE2" are defined in "Zend/zend_list.h" "php_stream_from_zval" is defined in "main/php_streams.h" "fgets" (the PHP function) is defined in "ext/standard/file.c" Note: Not ONE of these functions documents this behaviour and probably should... Even if it is a bug because all current and prior version are subject to this List of known functions affected: flock fclose pclose feof fgets fgetc fgetss fwrite fflush rewind ftell fseek fpassthru ftruncate fstat fread fgetcsv and any alias of named commands like "fputs" which is an alias for "fwrite"

« previous php.notes (#57377) next »