ZF-5806: Garbage piling up in $_SESSION when using Zend_Captcha

Description

I believe the session cleanup code in Zend_Session::_processStartupMetadataGlobal () should probably unset ($_SESSION['__ZF'][$namespace]) when ENT timeout hits.

Here is my problem:

I am using Zend_Captcha_Image to generate captchas for my site, and I noticed that if the captchas are not claimed, garbage accumulates in $_SESSION.

Zend_Captcha_Word sets two parameters for the session namespace:

$this->_session->setExpirationHops(1, null, true); $this->_session->setExpirationSeconds($this->getTimeout());

The resulting session looks like this:

Array ( [__ZF] => Array (

        [Zend_Form_Captcha_38b0306a2c96d5e34a0abb17cecfb1a8] => Array
            (
                [ENNH] => 1
                [ENT] => 1234830941
            )
    )

[Zend_Form_Captcha_38b0306a2c96d5e34a0abb17cecfb1a8] => Array
    (
        [word] => 4ibi7o
    )

)

i.e. it sets the session metadata $_SESSION[__ZF][$namespace][ENNH] (number of hops = 1) and $_SESSION[__ZF][$namespace][ENT] (timeout). Now if the captcha is claimed and validated, a new Zend_Session_Namespace object is created and in the constructor, the hop count is decreased and the ENNH parameter is removed, as well as the content $_SESSION[$namespace]. After the timeout, the ENT parameter is removed and $_SESSION[__ZF][$namespace] is cleaned up.

If the captcha is never claimed, the ENT timeout hits, and $_SESSION[__ZF][$namespace][ENT] and $_SESSION[__ZF][$namespace] are removed, but $_SESSION[__ZF][$namespace][ENNH] remains. The cleanup code:

        if (isset($namespace) && empty($_SESSION['__ZF'][$namespace])) {
            unset($_SESSION['__ZF'][$namespace]);

does not remove $_SESSION['__ZF'][$namespace] because the ENNH parameter is still there. Since the original namespace is never reinstantiated if the user never tries to validate the captcha, garbage accumulates in the session:

Array ( [__ZF] => Array ( [Zend_Form_Captcha_695b09f1d32dfc7ea02187e02faa2f91] => Array ( [ENNH] => 1 )

        [Zend_Form_Captcha_d1c1c089bec1e02fc3fb2e75c11a2860] => Array
            (
                [ENNH] => 1
            )

... }

In long running sessions, this may become substantial.

Now unless there is a compelling reason why the metadata needs to be kept after the content $_SESSION[$namespace] is gone, I believe the session cleanup code in _processStartupMetadataGlobal() should simply unset($_SESSION['__ZF'][$namespace]) after the ENT timeout, so no garbage accumulates in $_SESSION. I even suspect it might be best to simply delete the metadata in all places where $_SESSION[$namespace] is unset (e.g. also when ENNH hits 0).

Sorry if I am missing something.

Comments

This was one of the first things I noticed today when trying to implement captchas. I then tried to use my own session instead of letting it create one, but unfortunately there was a bug with setSession/generate as well.

Proposed patch for the issue

fixed in trunk