php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #15431 Resource destructor called too early
Submitted: 2002-02-07 13:58 UTC Modified: 2002-07-04 06:57 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: jonny at 1409 dot org Assigned:
Status: Closed Package: LDAP related
PHP Version: 4.1.1 OS: RedHat Linux 7.2
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jonny at 1409 dot org
New email:
PHP Version: OS:

 

 [2002-02-07 13:58 UTC] jonny at 1409 dot org
This bug is weird and it took me several days to track it down. But I have found a way to reproduce it, so please read on.

This might also be a general problem, not only LDAP related.

I have reproduced it connecting to a NDS-LDAP-Gateway and an Active Directory Server. Both only support LDAP v2, so it *might* not be reproducable with a v3 server.

To verify it I suggest to activate implicit flushing in php.ini and putting a php_printf() debug message into _free_ldap_result() in ldap.c, just before ldap_msgfree() gets called. This way you will see that the call to _free_ldap_result() will appear immediately after the PHP method get_entry() returns.
After verification comment out the ldap_msgfree() call and  you will notice that the segfault no longer occurs.

Here is the code, the critical places have comments and debug messages included:

  class ldap {

    function connect($server,$user="",$pw="") {
      $this->link=ldap_connect($server);
      $r=ldap_bind($this->link,$user,$pw);
    }

    function get_entry($dn) {
      $res=ldap_read($this->link,$dn,"objectclass=*");
      if (!$res) return false;

      print "*** calling ldap_first_entry()<br>\n";flush();
      $this->entry=ldap_first_entry($this->link, $res);
      if (!$this->entry) return false;

      print "*** returning from get_entry()<br>\n";
      return true;
    }

    function get_attributes() {
      if(!$this->entry) return false;

      print "*** calling ldap_get_attributes(), prepare ".
            "for segfault<br>\n";flush();
      // Apache will segfault *here*, as the LDAPMessage
      // was already freed!
      $this->attributes=ldap_get_attributes($this->link,
                                            $this->entry);

      if(!$this->attributes) return false;

      return true;
    }

    function print_entry($dn) {
      if (!$this->get_entry($dn)) return false;
      print "*** returned from get_entry()<br>\n";
      // _free_ldap_result from ldap.c gets called
      // although the resource is still referenced
      // through $this->entry!!

      if (!$this->get_attributes()) return false;

      for($i=0;$i<$this->attributes['count'];$i++) {
        $attrname=$this->attributes[$i];
        $values=$this->attributes[$attrname];
        for($j=0;$j<$values['count'];$j++) {
          print "- $attrname [$j]: ".$values[$j]."<br>\n";
        }
      }
    }
  }

  $ldap=new ldap();

  $ldap->connect("ldapserver.example.com", "ldapuser",
                 "ldappassword");

  $ldap->print_entry("CN=jonny,OU=User,DC=example,DC=com");

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-06-29 20:12 UTC] sniper@php.net
Some resource bug was fixed recently in CVS. Please try this snapshot:

http://snaps.php.net/php4-latest.tar.gz

 [2002-07-04 06:38 UTC] jonny at 1409 dot org
I've only taken ldap.c from the snapshot. The bugs seems to have gone. Thanks a lot!
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Jan 05 06:01:27 2025 UTC