confusing segmentation fault involving ldap_url_parse function from openldap library

142 views Asked by At

On a CentOS 6.6 server the following code compiles (with gcc version 4.4.7 or with clang version 3.4.2) without incident but results in a segmentation fault when run:

#include <ldap.h>

int main( int argc, char **argv )
{
    LDAPURLDesc **ludpp;
    int parse_status = ldap_url_parse("ldap://ldap.example.com", ludpp);
    char * str;
}

However if I modify it to remove the string declaration, like so:

#include <ldap.h>

int main( int argc, char **argv )
{
    LDAPURLDesc **ludpp;
    int parse_status = ldap_url_parse("ldap://ldap.example.com", ludpp);
}

then it runs without incident as well. On my Mac OS X 10.10.3 (Yosemite) both versions (with and without the string declaration) compile and run.

My three questions are:

  1. Why does the first example segfault on the CentOS server?
  2. Why does the second example NOT segfault on the CentOS server?
  3. What, specifically, is the difference between my Mac laptop and the Linux server that causes this disparity between the two?
1

There are 1 answers

2
John Bollinger On BEST ANSWER

You are intended to use the function like this:

#include <ldap.h>

int main( int argc, char **argv )
{
    LDAPURLDesc *ludp;
    int parse_status = ldap_url_parse("ldap://ldap.example.com", &ludp);
}

This allows the function to set the value that you will subsequently see in variable ludp (to a pointer to a dynamically-allocated parse result). Note that in this case, the second function argument is a valid pointer.

In your original code, however, you pass the value of an uninitialized pointer. This is absolutely useless, because there is no defined behavior for anything the function might do with that value. One of the more likely behaviors that could result is a segmentation fault, but such a result is by no means guaranteed (c.f. "undefined").

Also, your code is responsible for freeing the object provided in this way when it is no longer needed, which it should do via ldap_free_urldesc(). That doesn't matter in the test program, since it just exits immediately anyway, but if in a real program you just continue on then have a memory leak -- especially so if you lose the pointer provided by ldap_url_parse(), by overwriting it or letting it go out of scope.