Skip to content

Commit 093cb1d

Browse files
committed
Merge branch 'PHP-7.2'
* PHP-7.2: Fixed bug #75402 Possible Memory Leak using PDO::CURSOR_SCROLL option
2 parents 5674cf8 + d207d6a commit 093cb1d

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

ext/pdo_pgsql/pgsql_statement.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt)
163163
pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
164164
return 0;
165165
}
166+
PQclear(S->result);
166167

167168
/* the cursor was declared correctly */
168169
S->is_prepared = 1;
@@ -432,6 +433,11 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
432433
return 0;
433434
}
434435

436+
if(S->result) {
437+
PQclear(S->result);
438+
S->result = NULL;
439+
}
440+
435441
spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name);
436442
efree(ori_str);
437443
S->result = PQexec(S->H->server, q);

ext/pdo_pgsql/tests/bug75402.phpt

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
--TEST--
2+
PDO PgSQL Bug #75402 Possible Memory Leak using PDO::CURSOR_SCROLL option
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+
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
14+
15+
$resp = new \stdClass();
16+
$resp->entries = [];
17+
18+
$db->query('DROP TABLE IF EXISTS bug75402 CASCADE');
19+
$db->query('CREATE TABLE bug75402 (
20+
"id" character varying(64) NOT NULL,
21+
"group_id" character varying(64) NOT NULL,
22+
"submitter" character varying(320) NOT NULL,
23+
"operation" character varying(32) NOT NULL,
24+
"description" character varying(320) NOT NULL,
25+
"stage" character varying(16) NOT NULL,
26+
"status" character varying(64) NOT NULL,
27+
"progress" integer NOT NULL,
28+
"insert_datetime" timestamp(3) NOT NULL,
29+
"begin_datetime" timestamp(3),
30+
"end_datetime" timestamp(3),
31+
"life_hours" integer NOT NULL,
32+
"family" character varying(32) NOT NULL,
33+
"parallelism_group" character varying(32) NOT NULL,
34+
"max_parallelism" integer NOT NULL,
35+
"hidden" boolean NOT NULL,
36+
"abort" boolean NOT NULL,
37+
"order_folder_pathname" character varying(320),
38+
"worker" character varying(32) NOT NULL,
39+
CONSTRAINT "pk_bug75402" PRIMARY KEY ("id")
40+
) WITH (oids = false);');
41+
42+
43+
44+
$db->query("INSERT INTO bug75402 (\"id\", \"group_id\", \"submitter\", \"operation\", \"description\", \"stage\", \"status\", \"progress\", \"insert_datetime\", \"begin_datetime\", \"end_datetime\", \"life_hours\", \"family\", \"parallelism_group\", \"max_parallelism\", \"hidden\", \"abort\", \"order_folder_pathname\", \"worker\") VALUES
45+
('20171016083645_5337', 'G_20171016083645_5337', 'TESTPetunia', 'IMPORT', '', 'DON', 'Completed', 100, '2017-10-16 08:36:45', '2017-10-16 08:36:46', '2017-10-16 08:36:46', 96, 'IMPORT', '', -1, 'f', 'f', 'C:\ProgramData\TestPath\TestApp\Jobs\Jobs\\20171016083645_5337', 'MainService')");
46+
47+
48+
49+
$sql = "SELECT
50+
ID as \"sID\",
51+
GROUP_ID as \"sGroupID\",
52+
SUBMITTER as \"sOwner\",
53+
OPERATION as \"sOperation\",
54+
DESCRIPTION as \"sInfo\",
55+
STAGE as \"sShortStatus\",
56+
STATUS as \"sStatus\",
57+
PROGRESS as \"sProgress\",
58+
HIDDEN as \"bHidden\",
59+
to_char(INSERT_DATETIME, 'IYYY.MM.DD HH24:MI:SS') as \"sDatetime\"
60+
FROM bug75402
61+
ORDER BY INSERT_DATETIME DESC";
62+
63+
if ($db) {
64+
$stmt = $db->prepare($sql,
65+
array(
66+
// With the following options memory is not being
67+
// deallocated
68+
\PDO::ATTR_CURSOR => \PDO::CURSOR_SCROLL
69+
// With the following option memory is de-allocated
70+
// \PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY
71+
)
72+
);
73+
$stmt->execute();
74+
75+
while ($entry = $stmt->fetchObject()) {
76+
$resp->entries [] = $entry;
77+
}
78+
$stmt->closeCursor();
79+
$stmt = null;
80+
$db = null;
81+
}
82+
83+
var_dump($resp);
84+
85+
--EXPECT--
86+
object(stdClass)#2 (1) {
87+
["entries"]=>
88+
array(1) {
89+
[0]=>
90+
object(stdClass)#4 (10) {
91+
["sid"]=>
92+
string(19) "20171016083645_5337"
93+
["sgroupid"]=>
94+
string(21) "G_20171016083645_5337"
95+
["sowner"]=>
96+
string(11) "TESTPetunia"
97+
["soperation"]=>
98+
string(6) "IMPORT"
99+
["sinfo"]=>
100+
string(0) ""
101+
["sshortstatus"]=>
102+
string(3) "DON"
103+
["sstatus"]=>
104+
string(9) "Completed"
105+
["sprogress"]=>
106+
string(3) "100"
107+
["bhidden"]=>
108+
bool(false)
109+
["sdatetime"]=>
110+
string(19) "2017.10.16 08:36:45"
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)