|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69752 PDOStatement::execute() leaks memory with DML Statements when closeCuror() is u
Submitted: 2015-06-03 11:59 UTC Modified: 2015-06-10 15:48 UTC
Avg. Score:5.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: phofstetter at sensational dot ch Assigned: ab (profile)
Status: Closed Package: PDO PgSQL
PHP Version: 5.6.9 OS: MacOS X and Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
Solve the problem:
8 + 11 = ?
Subscribe to this entry?

 [2015-06-03 11:59 UTC] phofstetter at sensational dot ch
using PDO PGSql, when calling closeCursor() on a statement before re-using it in a future execute(), some amount of memory is leaked every time the statement is executed.

This only happens on DML statements (insert or update) and it only happens when closeCursor() is being called.

Test script:

printf("I'm pid %d\n", getmypid());

$pdo = new PDO('pgsql:dbname=somedb;user=someuser;host=');
$pdo->exec('discard all');
$pdo->exec("set client_encoding to 'utf-8'");

    create table foo (
        id bigserial not null primary key,
        field1 text not null,
        field2 text not null,
        field3 text not null,
        field4 int4 not null

// leaks
$stmt = $pdo->prepare("insert into foo (field1, field2, field3, field4) values (:field1, :field2, :field3, :field4)");

// also leaks
//$stmt = $pdo->prepare("update foo set field1 = :field1, field2 = :field2, field3 = :field3 where field4 = :field4");

// doesn't leak
//$stmt = $pdo->prepare("select * from foo where field1 = :field1 and field2 = :field2 and field3 = :field3 and field4 = :field4");

$max = 10000;
for($i = 0; $i < $max; $i++) {
    $data = array(
        'field1' => "field1: $i",
        'field2' => "field2: $i",
        'field3' => "field3: $i",
        'field4' => $i
    $stmt->closeCursor(); // leak goes away if closeCursor() is removed
    printf("\r%d", memory_get_usage(true)/1024);


Expected result:
printed memory usage should stay constant.

Actual result:
printed memory usage is continuously increasing.


Add a Patch

Pull Requests

Pull requests:

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-03 12:43 UTC] phofstetter at sensational dot ch
I'm not 100% sure and I'd like confirmation by somebody familiar with PDO, but I think this is what happens:

Once you call closeCursor(), PDOStatement will first call the driver specific closing function (which in case of postgres is a noop). Then, the parent implementation will set the executed member to 0. Here:

The postgres PDO driver calls ecealloc() depending on the state of that executed flag though. Like here:

But that memory is never freed if the `executed` member gets reset outside.

I'll try to find a clean solution and propose a pull request (with tests, of course)
 [2015-06-03 13:05 UTC] phofstetter at sensational dot ch
Based on the previous analysis, I came up with

which fixes the leak. I'll add tests and then create an official pull request.

Just giving a heads-up here so nobody starts working on this :-)
 [2015-06-05 07:02 UTC] phofstetter at sensational dot ch
With the attached pull request, all tests (including the new one that checks for the leak) pass now. Is there anything else you need from me?
 [2015-06-10 15:48 UTC]
-Status: Open +Status: Closed -Assigned To: +Assigned To: ab
 [2015-06-10 15:48 UTC]
The PR is merged in 5.5+.

PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Sat Jan 29 11:03:35 2022 UTC