ZF-6265: Zend Rest Result.php does not handle invalid XML properly - error handlers are ignored

Description

If you take a look at file Zend/Rest/Result.php you'll see in the __construct method the following code:


 public function __construct($data)
    {
        set_error_handler(array($this, 'handleXmlErrors'));
        $this->_sxml = simplexml_load_string($data);
        if($this->_sxml === false) {
            $this->handleXmlErrors(0, "An error occured while parsing the REST response with simplexml.");
        } else {
            restore_error_handler();
        }
    }

you're setting the error handler to use "handleXmlErrors" which in that method it attempts to restore the error handler and throw an exception. If you take a look at the php docs http://us.php.net/restore_error_handler you'll see the NOTE: Note: Calling restore_error_handler() from the error_handler function is ignored.

Which means once the error occurs it jumps into handleXmlErrors and the restore called is ignored and when the exception is thrown execution stops at the simplexml_load_string line and is passed backed to the caller. The restoration of the error handler never occurs. To work around I had to restore the error handler in my controller in the "catch" section of my try catch .

Comments

I've stumbled across this one as well. Something like the following patch could fix it, but for some reason the error string that I store in $this->_errstr gets chopped after leaving the error handler function:

Index: Result.php
===================================================================
--- Result.php  (revision 16697)
+++ Result.php  (working copy)
@@ -32,6 +32,8 @@
      */
     protected $_sxml;
 
+    private $_errstr = false;
+
     /**
      * Constructor
      *
@@ -42,10 +44,14 @@
     {
         set_error_handler(array($this, 'handleXmlErrors'));
         $this->_sxml = simplexml_load_string($data);
+        restore_error_handler();
         if($this->_sxml === false) {
-            $this->handleXmlErrors(0, "An error occured while parsing the REST response with simplexml.");
-        } else {
-            restore_error_handler();
+            require_once "Zend/Rest/Client/Result/Exception.php";
+            if (isset($this->_errstr)) {
+                throw new Zend_Rest_Client_Result_Exception("REST Response Error: ".$this->_errstr);
+            } else {
+                throw new Zend_Rest_Client_Result_Exception("An error occured while parsing the REST response with simplexml.");
+            }
         }
     }
 
@@ -57,13 +63,10 @@
      * @param string $errfile
      * @param string $errline
      * @param array  $errcontext
-     * @throws Zend_Result_Client_Result_Exception
      */
     public function handleXmlErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null)
     {
-        restore_error_handler();
-        require_once "Zend/Rest/Client/Result/Exception.php";
-        throw new Zend_Rest_Client_Result_Exception("REST Response Error: ".$errstr);
+        $this->_errstr = $errstr;
     }
 
     /**

Solved in SVN r18973.

I think it could be next mini release if the handleXmlErrors() would be private.

But now it should be next minor to avoid BC problem, I think.