ZF-5221: Zend_Http_CookieJar::_matchDomain() does not match domains with a dot prepended

Description


// This is /1.php
// Suppose a cookie is set with:
setcookie('foo', 'bar', time() + 86400, '/', '.zend.com');
// With a dot prepended to zend.com, the cookie is also made available to all subdomains.

// This is /2.php
var_dump($_COOKIE);

// test.php
$request = new Zend_Http_Client();
$request->setCookieJar();

$request->setUri('http://zend.com/1.php');
$request->request();

$request->setUri('http://zend.com/2.php');
$response = $request->request();

echo $response->getBody();
// Output from the var_dump() in /2.php:
// array(0) {
// }

Comments

Set component and auto reassign

Zend_Http_Cookie::match() also doesn't match due to the same cause.

These modifications seem to have fixed them:


Zend/Http/Cookie.php:

@@ -232,9 +232,16 @@
         if ($this->isSessionCookie() && ! $matchSessionCookies) return false;
 
         // Validate domain and path
-        // Domain is validated using tail match, while path is validated using head match
-        $domain_preg = preg_quote($this->getDomain(), "/");
-        if (! preg_match("/{$domain_preg}$/", $uri->getHost())) return false;
+        // Domain is validated using exact or tail match, while path is validated using head match
+        $domain = $this->getDomain();
+        $host = $uri->getHost();
+        $domain_preg = preg_quote($domain, '/');
+        if (
+            !preg_match("/{$domain_preg}$/", $host) &&
+            (($domain[0] === '.') && (strcasecmp(substr($domain, 1), $host) !== 0))
+        ) {
+            return false;
+        }
         $path_preg = preg_quote($this->getPath(), "/");
         if (! preg_match("/^{$path_preg}/", $uri->getPath())) return false;

Zend/Http/CookieJar.php:

@@ -297,8 +297,12 @@
         $ret = array();
 
         foreach (array_keys($this->cookies) as $cdom) {
-            $regex = "/" . preg_quote($cdom, "/") . "$/i";
-            if (preg_match($regex, $domain)) $ret[$cdom] = &$this->cookies[$cdom];
+                   if (($cdom[0] === '.') && (strcasecmp(substr($cdom, 1), $domain) === 0)) {
+                $ret[$cdom] = &$this->cookies[$cdom];
+                   } else {
+                $regex = "/" . preg_quote($cdom, "/") . "$/i";
+                if (preg_match($regex, $domain)) $ret[$cdom] = &$this->cookies[$cdom];
+            }
         }
 
         return $ret;

Congrats, fixed in rev. 17079 - thanks for reporting and for the patience :)

I set fix version. I find this at SVN r17118 in 1.9 branch.