Skip to content

Commit 2ca86bb

Browse files
committed
Merge branch 'PHP-7.0'
* PHP-7.0: Add test for bug #72294 Fixed bug #72294 Segmentation fault/invalid pointer in connection with pgsql_stmt_dtor
2 parents 1afcf15 + 79b978d commit 2ca86bb

File tree

2 files changed

+164
-11
lines changed

2 files changed

+164
-11
lines changed

ext/pdo_pgsql/pgsql_statement.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
6262
{
6363
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
64+
zend_bool server_obj_usable = IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)])
65+
&& !(GC_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED);
6466

6567
if (S->result) {
6668
/* free the resource */
@@ -69,11 +71,11 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
6971
}
7072

7173
if (S->stmt_name) {
72-
pdo_pgsql_db_handle *H = S->H;
73-
char *q = NULL;
74-
PGresult *res;
74+
if (S->is_prepared && server_obj_usable) {
75+
pdo_pgsql_db_handle *H = S->H;
76+
char *q = NULL;
77+
PGresult *res;
7578

76-
if (S->is_prepared) {
7779
spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name);
7880
res = PQexec(H->server, q);
7981
efree(q);
@@ -106,14 +108,16 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
106108
}
107109

108110
if (S->cursor_name) {
109-
pdo_pgsql_db_handle *H = S->H;
110-
char *q = NULL;
111-
PGresult *res;
111+
if (server_obj_usable) {
112+
pdo_pgsql_db_handle *H = S->H;
113+
char *q = NULL;
114+
PGresult *res;
112115

113-
spprintf(&q, 0, "CLOSE %s", S->cursor_name);
114-
res = PQexec(H->server, q);
115-
efree(q);
116-
if (res) PQclear(res);
116+
spprintf(&q, 0, "CLOSE %s", S->cursor_name);
117+
res = PQexec(H->server, q);
118+
efree(q);
119+
if (res) PQclear(res);
120+
}
117121
efree(S->cursor_name);
118122
S->cursor_name = NULL;
119123
}

ext/pdo_pgsql/tests/bug72294.phpt

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
--TEST--
2+
Bug #72294 Segmentation fault/invalid pointer in connection with pgsql_stmt_dtor
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
6+
require dirname(__FILE__) . '/config.inc';
7+
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
8+
PDOTest::skip();
9+
?>
10+
--FILE--
11+
<?php
12+
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
13+
14+
function handleError($errno, $errstr, $errfile, $errline)
15+
{
16+
if (!($errno & error_reporting())) {
17+
return false;
18+
}
19+
20+
throw new RuntimeException( $errstr, $errno );
21+
}
22+
23+
abstract class PHPUnit_Framework_TestCase
24+
{
25+
private $name = null;
26+
private $result;
27+
28+
public function run(PHPUnit_Framework_TestResult $result = null)
29+
{
30+
$result->run($this);
31+
}
32+
33+
public function runBare()
34+
{
35+
$class = new ReflectionClass($this);
36+
$method = $class->getMethod($this->name);
37+
$method->invoke($this);
38+
39+
if( $x ) {
40+
}
41+
}
42+
43+
public function setName($name)
44+
{
45+
$this->name = $name;
46+
}
47+
}
48+
49+
class PHPUnit_Framework_TestFailure
50+
{
51+
private $testName;
52+
53+
protected $failedTest;
54+
55+
protected $thrownException;
56+
57+
public function __construct( $failedTest, $t)
58+
{
59+
if ($failedTest instanceof PHPUnit_Framework_SelfDescribing) {
60+
$this->testName = $failedTest->toString();
61+
} else {
62+
$this->testName = get_class($failedTest);
63+
}
64+
65+
$this->thrownException = $t;
66+
}
67+
}
68+
69+
class PHPUnit_Framework_TestResult
70+
{
71+
public function run( $test)
72+
{
73+
$error = false;
74+
75+
$oldErrorHandler = set_error_handler(
76+
'handleError',
77+
E_ALL | E_STRICT
78+
);
79+
80+
try {
81+
$test->runBare();
82+
} catch (RuntimeException $e) {
83+
$error = true;
84+
}
85+
86+
restore_error_handler();
87+
88+
if ($error === true) {
89+
$this->errors[] = new PHPUnit_Framework_TestFailure($test, $e);
90+
}
91+
}
92+
}
93+
94+
$result = new PHPUnit_Framework_TestResult();
95+
96+
class PreparedStatementCache
97+
{
98+
private $cached_statements = array();
99+
100+
public function prepare( $pdo, $sql )
101+
{
102+
//return $pdo->prepare( $sql );
103+
$this->cached_statements[$sql] = $pdo->prepare( $sql );
104+
105+
return $this->cached_statements[$sql];
106+
}
107+
}
108+
109+
class DatabaseTest extends PHPUnit_Framework_TestCase
110+
{
111+
public function testIt()
112+
{
113+
$pdo = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
114+
115+
$prepared_statement_cache = new PreparedStatementCache( $pdo );
116+
117+
for( $i = 1; $i <= 300; ++$i ) {
118+
$statement = $prepared_statement_cache->prepare( $pdo, <<<SQL
119+
SELECT $i;
120+
SQL
121+
);
122+
$statement->execute();
123+
}
124+
}
125+
126+
public function test_construct()
127+
{
128+
$pdo = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
129+
130+
$pdo->exec( 'CREATE TEMPORARY TABLE temp_table ( test_column INT NOT NULL );' );
131+
132+
$this->cache = new PreparedStatementCache( $pdo );
133+
134+
$statement = $this->cache->prepare( $pdo, 'SELECT * FROM temp_table WHERE test_column > 0' );
135+
$statement->execute();
136+
}
137+
}
138+
139+
$test = new DatabaseTest();
140+
$test->setName( 'testIt' );
141+
$test->run( $result );
142+
$test->setName( 'test_construct' );
143+
$test->run( $result );
144+
145+
?>
146+
==NOCRASH==
147+
--EXPECT--
148+
==NOCRASH==
149+

0 commit comments

Comments
 (0)