Skip to content
This repository was archived by the owner on Jan 31, 2020. It is now read-only.

Commit f5475c4

Browse files
committed
Merge branch 'hotfix/51'
Close #51
2 parents c0e5922 + 64a3697 commit f5475c4

File tree

4 files changed

+83
-4
lines changed

4 files changed

+83
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ All notable changes to this project will be documented in this file, in reverse
1818

1919
### Fixed
2020

21-
- Nothing.
21+
- [#51](https://github.com/zendframework/zend-session/pull/51) provides a fix to
22+
the `DbTableGateway` save handler to prevent infinite recursion when
23+
attempting to destroy an expired record during initial read operations.
2224

2325
## 2.7.2 - 2016-06-24
2426

src/SaveHandler/DbTableGateway.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ public function close()
9090
* Read session data
9191
*
9292
* @param string $id
93+
* @param bool $destroyExpired Optional; true by default
9394
* @return string
9495
*/
95-
public function read($id)
96+
public function read($id, $destroyExpired = true)
9697
{
9798
$rows = $this->tableGateway->select([
9899
$this->options->getIdColumn() => $id,
@@ -104,7 +105,9 @@ public function read($id)
104105
$row->{$this->options->getLifetimeColumn()} > time()) {
105106
return (string) $row->{$this->options->getDataColumn()};
106107
}
107-
$this->destroy($id);
108+
if ($destroyExpired) {
109+
$this->destroy($id);
110+
}
108111
}
109112
return '';
110113
}
@@ -149,7 +152,7 @@ public function write($id, $data)
149152
*/
150153
public function destroy($id)
151154
{
152-
if (! (bool) $this->read($id)) {
155+
if (! (bool) $this->read($id, false)) {
153156
return true;
154157
}
155158

test/SaveHandler/DbTableGatewayTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Zend\Session\SaveHandler\DbTableGatewayOptions;
1414
use Zend\Db\Adapter\Adapter;
1515
use Zend\Db\TableGateway\TableGateway;
16+
use ZendTest\Session\TestAsset\TestDbTableGatewaySaveHandler;
1617

1718
/**
1819
* Unit testing for DbTableGateway include all tests for
@@ -168,6 +169,38 @@ public function testDestroyReturnsTrueWhenSessionIsDeleted()
168169
$this->assertTrue($result);
169170
}
170171

172+
public function testExpiredSessionDoesNotCauseARecursion()
173+
{
174+
// puts an expired session in the db
175+
$query = "
176+
INSERT INTO `sessions` (
177+
`{$this->options->getIdColumn()}`,
178+
`{$this->options->getNameColumn()}`,
179+
`{$this->options->getModifiedColumn()}`,
180+
`{$this->options->getLifetimeColumn()}`,
181+
`{$this->options->getDataColumn()}`
182+
) VALUES (
183+
'123', 'zend-session-test', ".(time() - 31).", 30, 'foobar'
184+
);
185+
";
186+
$this->adapter->query($query, Adapter::QUERY_MODE_EXECUTE);
187+
188+
$this->usedSaveHandlers[] = $saveHandler = new TestDbTableGatewaySaveHandler($this->tableGateway, $this->options);
189+
$saveHandler->open('savepath', 'zend-session-test');
190+
191+
$this->assertSame(0, $saveHandler->getNumReadCalls());
192+
$this->assertSame(0, $saveHandler->getNumDestroyCalls());
193+
194+
$success = (boolean) $saveHandler->read('123');
195+
$this->assertFalse($success);
196+
197+
$this->assertSame(2, $saveHandler->getNumReadCalls());
198+
$this->assertSame(1, $saveHandler->getNumDestroyCalls());
199+
200+
// cleans the test record from the db
201+
$this->adapter->query("DELETE FROM `sessions` WHERE `{$this->options->getIdColumn()}` = '123';");
202+
}
203+
171204
/**
172205
* Sets up the database connection and creates the table for session data
173206
*
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace ZendTest\Session\TestAsset;
11+
12+
use Zend\Session\SaveHandler\DbTableGateway;
13+
14+
class TestDbTableGatewaySaveHandler extends DbTableGateway
15+
{
16+
protected $numReadCalls = 0;
17+
18+
protected $numDestroyCalls = 0;
19+
20+
public function getNumReadCalls()
21+
{
22+
return $this->numReadCalls;
23+
}
24+
25+
public function getNumDestroyCalls()
26+
{
27+
return $this->numDestroyCalls;
28+
}
29+
30+
public function read($id, $destroyExpired = true)
31+
{
32+
$this->numReadCalls++;
33+
return parent::read($id, $destroyExpired);
34+
}
35+
36+
public function destroy($id)
37+
{
38+
$this->numDestroyCalls++;
39+
return parent::destroy($id);
40+
}
41+
}

0 commit comments

Comments
 (0)