php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75190 Impossible to close PDO connection when extending PdoStatement using $this
Submitted: 2017-09-11 15:58 UTC Modified: -
From: ian at oshaughnessy dot cc Assigned:
Status: Open Package: PDO related
PHP Version: 7.0.23 OS: Debian 9
Private report: No CVE-ID:
Have you experienced this issue?
Rate the importance of this bug to you:

 [2017-09-11 15:58 UTC] ian at oshaughnessy dot cc
Description:
------------
The only way to close a PDO connection is to set the resource variable to null (thereby destroying the PDO object); however, when extending the PdoStatement class, it's required that $this is passed as an option to the PDO object for Pdo::ATTR_STATEMENT_CLASS.

In doing this, a reference to the PDO object is created, making it impossible to destroy the PDO object since a lingering reference continues to exist after $pdo is set to null.

The only way to fix this issue is to use Pdo::setAttribute() after the PDO parent constructor has been run.

Test script:
---------------
<?php

echo "Test 1 (PdoTestBroken)\n";
echo "new PdoTestBroken\n";
$pdo1 = new PdoTestBroken($dsn, $username, $password, []);
echo "Destroy \$pdo\n";
$pdo1 = null;
echo "----------------------------\n\n";

echo "Test 2 (PdoTestWorks)\n";
echo "new PdoTestWorks\n";
$pdo2 = new PdoTestWorks($dsn, $username, $password, []);
echo "Destroy \$pdo\n";
$pdo2 = null;
echo "----------------------------\n\n";

class PdoTestBroken extends Pdo {

	public function __construct($dsn, $username, $passwd, $options) {
		echo "PdoTest1::__construct()\n";
		$options[self::ATTR_STATEMENT_CLASS] = [ 'PdoStatementTest', [ $this, ] ];
		parent::__construct($dsn, $username, $passwd, $options);
	}

	public function __destruct() {
		echo "PdoTest1::__destruct()\n";
	}
}

class PdoTestWorks extends Pdo {

	public function __construct($dsn, $username, $passwd, $options) {
		echo "PdoTest2::__construct()\n";
		$self = parent::__construct($dsn, $username, $passwd, $options);
		$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [ 'PdoStatementTest', [ $self, ] ]);
	}

	public function __destruct() {
		echo "PdoTest2::__destruct()\n";
	}
}

class PdoStatementTest extends PdoStatement {

}

Expected result:
----------------
The connection to close.


Actual result:
--------------
The connection does not close due to hidden reference variable.

Script Results:

Test 1 (PdoTestBroken)
new PdoTestBroken
PdoTest1::__construct()
Destroy $pdo
----------------------------

Test 2 (PdoTestWorks)
new PdoTestWorks
PdoTest2::__construct()
Destroy $pdo
PdoTest2::__destruct()
----------------------------

PdoTest1::__destruct()

Patches

Add a Patch

Pull Requests

Add a Pull Request

 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC