php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #18494 DB::query leaks memory
Submitted: 2002-07-23 11:13 UTC Modified: 2003-06-11 12:10 UTC
From: sam at ananova dot com Assigned: ssb (profile)
Status: Closed Package: PEAR related
PHP Version: 4.2.0 OS: linux redhat 7.3 up2date-ed
Private report: No CVE-ID: None
 [2002-07-23 11:13 UTC] sam at ananova dot com
  $result=$this->db->query($sql,$values);
 
makes use of "prepare" internally and doesn't free the results.
 
e.g., the following script, does one query 5 times and annother time with different values, yet when done, diagnose() prints out that 6 lots of prepare_tokens, prepare_types, prepare_queries were stored in the db object!

I reckon at least they should have been destroyed when the results were destroyed (if no results, then right away!).

<?php

include_once("DB.php");

$_db=array(
    'phptype'  => "pgsql",
    'hostspec' => "localhost",
    'database' => "*****",
    'username' => "*******",
    'protocol' => "unix",
    'password' => "***********");

$db=DB::connect($_db);
if (DB::isError($db)) {
  die("Can't connect");
}

$sql="select ?";
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(2));

var_dump($db);
diagnose($db);

function diagnose(&$db) {
  foreach($db as $key=>$val) if (eregi('^prepare',$key) && is_array($val)) {
    print count($val). " of $key\n";
  }
}

function QUERY(&$db,$sql,$array) {
  $result=$db->query($sql,array(1));
  if (DB::isError($result)) {
    die ("Dead: ".$result->userinfo);
  }
  $numRows=$result->numRows();
  if ($numRows>1) die ("Too many matches for $query,");
  if ($numRows) {
    $data=$result->fetchRow(DB_FETCHMODE_ASSOC);
  }
  if (is_object($result)) $result->free();
  return $data;
}
?>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-04-28 04:01 UTC] arnaud@php.net
changing status
 [2003-05-04 12:16 UTC] lsmith@php.net
I think this is a general problem with the various methods in PEAR::DB that prepare and execute in one go and return a result set. This way the user never gets the prepared "id". Therefore PEAR::DB should free these for the user (since the user can't use the id again anyways).

Like so:
733c733,735
<             return $this->execute($sth, $params);
---
>             $result = $this->execute($sth, $params);
>             $this->freeResult($sth);
>             return $result;

But somebody has to go through and probably look at every instance of return $this->execute() where the user did not pass a prepare ID. (Did I mention before that this is imho is abuse of prepare/execute and if you want this sort of seperation of data and query structure you should use a layer ontop of PEAR::DB .. my 2 cents)
 [2003-06-11 12:10 UTC] cox@php.net
I've fixed that, avaible in CVS, by adding a new $db_object->freePrepared() method and calling it from all the functions that doesn't expose the prepared statement.

Thanks for reporting
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Sun Aug 01 14:01:24 2021 UTC