Issue 4690 - segfault in ldap_count_values() with PHP
Summary: segfault in ldap_count_values() with PHP
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: build (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-01 08:12 UTC by madcoder@gmail.com
Modified: 2014-08-01 21:05 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description madcoder@gmail.com 2006-10-01 08:12:02 UTC
Full_Name: Joe H
Version: 2.3.24
OS: gentoo linux (2.6.17) on amd64 Athlon X2
URL: http://bugs.php.net/bug.php?id=38819
Submission from: (NULL) (70.245.125.224)


I'm not certain yet whether this is a bug in openldap, or in PHP, but my bug
report with PHP has stalled, so I am hoping that cross-posting it here might
garnish some further insight into the problem.

The PHP bug report should explain the segfault I'm experiencing, and where the
segfault occurs.  It can be found at http://bugs.php.net/bug.php?id=38819

The segfault occurs in libraries/libldap/getvalues.c, in the ldap_count_values()
function.  The value for vals that is passed to the function cannot be read for
some reason.  At first I thought this might be a PHP problem, since the
ldapsearch utility works fine performing the same search.  However, it should
also be mentioned that the value that is sent to ldap_get_values, is a value
returned directly from ldap_get_values():

> ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute);
> num_values = ldap_count_values(ldap_value);

While in ldap_count_values(), the backtrace shows that the segfault occurs
during the first iteration of the for() loop:

> Program received signal SIGSEGV, Segmentation fault.
> 0x00002b2871ad210b in ldap_count_values (vals=0x55a170c0) at getvalues.c:152
> 152             for ( i = 0; vals[i] != NULL; i++ )

Further investigating the problem shows:

> (gdb) p i
> $1 = 0
> (gdb) p vals
> $2 = (char **) 0x55a170c0
> (gdb) p vals[0]
> Cannot access memory at address 0x55a170c0

The memory address changes obviously, but the segfault always occurs at that
point.

In PHP's ldap_get_entries() function, ldap_values is defined as:

> char **ldap_value;

which is the data type expected by ldap_count_entries().  Fetching the entry
reference itself, or counting the number of entries, does not cause the segfault
-- only when getting values from the entry.  For example, PHP's
ldap_first_entry($result) works fine (as well as iterating over the entries
using ldap_next_entry()), but trying to read any of the values within the entry
will cause the segfault.

Again, the fact that it works fine with ldapsearch, but segfaults in PHP, lead
me to believe that it would be a PHP problem, but looking more into the source
code of both applications makes me lean more and more to some obscure problem in
OpenLDAP's code.  The value of 'vals' is declared and returned from this
function:

> char **
> ldap_get_values( LDAP *ld, LDAPMessage *entry, LDAP_CONST char *target )
> {
>>...
>         char            **vals;
>>...
>         if ( (res = ber_scanf( &ber, "[v]", &vals )) == LBER_ERROR ) {
>                 ld->ld_errno = LDAP_DECODING_ERROR;
>                 return( NULL );
>         }
>         return( vals );

The return value of ber_scanf is 4, but I haven't investigated what that value
indicates (it is obviously not LBER_ERROR).  In any case, that value of 'vals'
is allocated inside OpenLDAP's code, and that makes me believe that it is not a
problem with PHP's code.  The same test script functions properly on a similar
32-bit system (as similar as 32- and 64-bit systems can be).

What more can I do to debug this problem?

Comment 1 ando@openldap.org 2006-10-02 00:11:20 UTC
madcoder@gmail.com wrote:
> What more can I do to debug this problem?
>   
Well, I've posted a bug to PHP about their using deprecated LDAP code, 
but it was basically bounced with "mind your own business" or sort of 
(and this __IS__ my own business, by the way :).  You could try 
rebuilding PHP's LDAP stuff defining -DLDAP_DEPRECATED=1 and see what 
happens.  I've seen similar problems with AMD64 when functions got 
linked without a prototype, and ldap_get_values does not have a 
prototype in ldap.h unless the above is defined.

p.



Ing. Pierangelo Masarati
OpenLDAP Core Team

SysNet s.n.c.
Via Dossi, 8 - 27100 Pavia - ITALIA
http://www.sys-net.it
------------------------------------------
Office:   +39.02.23998309
Mobile:   +39.333.4963172
Email:    pierangelo.masarati@sys-net.it
------------------------------------------

Comment 2 ando@openldap.org 2006-10-02 00:16:52 UTC
madcoder@gmail.com wrote:
...
You know, what makes me mad about PHP is that it internally uses 
something comparable to bervals, since the abstract type they use to 
wrap strings takes care of the length of the string itself; but in the 
LDAP extension, ldap_get_values() is used everywhere, and then strlen is 
run to compute the length of the values!  Why on earth don't they get 
ldap_get_values_len() should be used instead?  Somehow it got hardwired 
in people's brain that ldap_get_values_len() is only good for "binary" 
(that is, non-printable) stuff, and not for strings as well!

p.



Ing. Pierangelo Masarati
OpenLDAP Core Team

SysNet s.n.c.
Via Dossi, 8 - 27100 Pavia - ITALIA
http://www.sys-net.it
------------------------------------------
Office:   +39.02.23998309
Mobile:   +39.333.4963172
Email:    pierangelo.masarati@sys-net.it
------------------------------------------

Comment 3 ando@openldap.org 2006-10-02 00:17:21 UTC
changed notes
Comment 4 ando@openldap.org 2006-10-02 00:20:28 UTC
changed notes
Comment 5 ando@openldap.org 2006-10-02 00:21:02 UTC
changed notes
changed state Open to Feedback
Comment 6 Kurt Zeilenga 2006-10-02 02:35:51 UTC
At 06:12 PM 10/1/2006, ando@sys-net.it wrote:
>madcoder@gmail.com wrote:
>...
>You know, what makes me mad about PHP is that it internally uses 
>something comparable to bervals, since the abstract type they use to 
>wrap strings takes care of the length of the string itself; but in the 
>LDAP extension, ldap_get_values() is used everywhere, and then strlen is 
>run to compute the length of the values!  Why on earth don't they get 
>ldap_get_values_len() should be used instead?  Somehow it got hardwired 
>in people's brain that ldap_get_values_len() is only good for "binary" 
>(that is, non-printable) stuff, and not for strings as well!

Folks also tend to forget that U+0000 is a valid Unicode
character, as is ASCII 0...  but I digress.

Kurt 

Comment 7 ando@openldap.org 2006-10-02 13:24:15 UTC
changed notes
changed state Feedback to Closed
moved from Incoming to Build
Comment 8 Howard Chu 2009-02-17 07:03:30 UTC
moved from Build to Archive.Build
Comment 9 OpenLDAP project 2014-08-01 21:05:12 UTC
PHP needs to build with -DLDAP_DEPRECATED=1
see ITS#4168