https://bugs.openldap.org/show_bug.cgi?id=10563
Issue ID: 10563 Summary: ldap_count_message() returns '1' even with empty LDAPMessage as input. Product: OpenLDAP Version: 2.6.13 Hardware: All OS: All Status: UNCONFIRMED Keywords: needs_review Severity: normal Priority: --- Component: libraries Assignee: bugs@openldap.org Reporter: feh@fehcom.de Target Milestone: ---
Source: libldap/messages.c
The function
int ldap_count_messages( LDAP *ld, LDAPMessage *chain )
given *chain is NULL will return a '1' as result.
Line numbers included:
49 int 50 ldap_count_messages( LDAP *ld, LDAPMessage *chain ) 51 { 52 int i; 53 54 assert( ld != NULL ); 55 assert( LDAP_VALID( ld ) ); 56 57 for ( i = 0; chain != NULL; chain = chain->lm_chain ) { 58 i++; 59 } 60 61 return( i ); 62 }
It would be sufficient to test the LDAP message *chain in the following way before the for loop is executed:
line 56: if (!chain && !*chain) return ( 0 );
--eh.
https://bugs.openldap.org/show_bug.cgi?id=10563
Howard Chu hyc@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID
--- Comment #1 from Howard Chu hyc@openldap.org --- An empty message is still a message. There is no bug here.
https://bugs.openldap.org/show_bug.cgi?id=10563
Erwin Hoffmann feh@fehcom.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|INVALID |FIXED
--- Comment #2 from Erwin Hoffmann feh@fehcom.de --- Hi Hu,
how to differentiate an 'empty' message given return 1 and a message with content giving return 1 as well?
Following this test - and getting a '1' - I do the standard loop to get a message with 'ldap_first_message' and 'ldap_next_message.
This core dumps with content '0'; thus the above default solution given, makes no sense to me.
In particular the man ldap_message_count says:
"A count of the number of messages in the result chain can be obtained by calling ldap_count_messages(). "
This is very counter-intuitive.
Regards. --eh.
https://bugs.openldap.org/show_bug.cgi?id=10563
--- Comment #3 from Erwin Hoffmann feh@fehcom.de --- Sorry, I should say Howard Chu and not Hu.
https://bugs.openldap.org/show_bug.cgi?id=10563
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords|needs_review | Resolution|FIXED |INVALID
https://bugs.openldap.org/show_bug.cgi?id=10563
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |VERIFIED
https://bugs.openldap.org/show_bug.cgi?id=10563
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Target Milestone|--- |2.6.15 Resolution|INVALID |--- Status|VERIFIED |UNCONFIRMED
https://bugs.openldap.org/show_bug.cgi?id=10563
--- Comment #4 from Quanah Gibson-Mount quanah@openldap.org --- Please provide a reproducer for the segfault.
https://bugs.openldap.org/show_bug.cgi?id=10563
--- Comment #5 from Erwin Hoffmann feh@fehcom.de --- Hi Quanah,
I did a very basic loop over the results. Here is my code:
LDAP *ld; LDAPMessage *result, *msg, *entry; unsigned long scope = LDAP_SCOPE_BASE; char *search = "mail"; char **mail; char *mailfrom;
....
if ((r = ldap_search_ext_s(ld,binddn.s,scope,filters.s,NULL,0,NULL,NULL,NULL,LDAP_NO_LIMIT,&result)) != LDAP_SUCCESS) { log_error("search failed: ",ldap_err2string(r),"ERROR"); exit(110); }
for (msg = ldap_first_message(ld,result); msg != NULL; msg = ldap_next_message(ld,msg)) switch (ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: entry = ldap_first_entry(ld,result); if (!entry) { ldap_unbind(ld); exit(1); } // Not found case LDAP_RES_SEARCH_RESULT: mail = ldap_get_values(ld,entry,search);
for (int i = 0; i < ldap_count_values(mail); ++i) if (case_equals(mailfrom,mail[i])) addrok++; }
Thus, in case ldap_count_values() returns with '1' even for none-existing mail objects, any lookup in the structure will give you a core-dump.
Thanks for looking at this.
The algorithm works well for the 'deprecated' LDAP modules now in place. --eh.
https://bugs.openldap.org/show_bug.cgi?id=10563
--- Comment #6 from Erwin Hoffmann feh@fehcom.de --- Hi Quanah,
I forget to mention a link to the working code:
https://www.fehcom.de/sqmail/doxygen/qmail-ldapam_8c.html
Unfortunately, doxygen has no clue about a 'static exit' function, so it links it wrongly ;-)
--eh.
https://bugs.openldap.org/show_bug.cgi?id=10563
--- Comment #7 from Howard Chu hyc@openldap.org --- (In reply to Erwin Hoffmann from comment #5)
Hi Quanah,
I did a very basic loop over the results. Here is my code:
LDAP *ld; LDAPMessage *result, *msg, *entry; unsigned long scope = LDAP_SCOPE_BASE; char *search = "mail"; char **mail; char *mailfrom;
....
if ((r = ldap_search_ext_s(ld,binddn.s,scope,filters.s,NULL,0,NULL,NULL,NULL, LDAP_NO_LIMIT,&result)) != LDAP_SUCCESS) { log_error("search failed: ",ldap_err2string(r),"ERROR"); exit(110); }
for (msg = ldap_first_message(ld,result); msg != NULL; msg = ldap_next_message(ld,msg)) switch (ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: entry = ldap_first_entry(ld,result); if (!entry) { ldap_unbind(ld); exit(1); } // Not found case LDAP_RES_SEARCH_RESULT: mail = ldap_get_values(ld,entry,search);
for (int i = 0; i < ldap_count_values(mail); ++i) if (case_equals(mailfrom,mail[i])) addrok++;}
Thus, in case ldap_count_values() returns with '1' even for none-existing mail objects, any lookup in the structure will give you a core-dump.
Thanks for looking at this.
The algorithm works well for the 'deprecated' LDAP modules now in place. --eh.
Your initial report is about ldap_count_messages() but your example code uses ldap_count_values(). Which is it?
https://bugs.openldap.org/show_bug.cgi?id=10563
--- Comment #8 from Howard Chu hyc@openldap.org --- (In reply to Erwin Hoffmann from comment #5)
Hi Quanah,
I did a very basic loop over the results. Here is my code:
LDAP *ld; LDAPMessage *result, *msg, *entry; unsigned long scope = LDAP_SCOPE_BASE; char *search = "mail"; char **mail; char *mailfrom;
....
if ((r = ldap_search_ext_s(ld,binddn.s,scope,filters.s,NULL,0,NULL,NULL,NULL, LDAP_NO_LIMIT,&result)) != LDAP_SUCCESS) { log_error("search failed: ",ldap_err2string(r),"ERROR"); exit(110); }
for (msg = ldap_first_message(ld,result); msg != NULL; msg = ldap_next_message(ld,msg)) switch (ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: entry = ldap_first_entry(ld,result); if (!entry) { ldap_unbind(ld); exit(1); } // Not found case LDAP_RES_SEARCH_RESULT: mail = ldap_get_values(ld,entry,search);
for (int i = 0; i < ldap_count_values(mail); ++i) if (case_equals(mailfrom,mail[i])) addrok++;}
Thus, in case ldap_count_values() returns with '1' even for none-existing mail objects, any lookup in the structure will give you a core-dump.
This code is invalid. If "mail" is non-existing, ldap_get_values() returns a NULL pointer. You can't pass a NULL pointer to ldap_count_values(). Your program is broken and there is no OpenLDAP bug here.
https://bugs.openldap.org/show_bug.cgi?id=10563
Howard Chu hyc@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID
--- Comment #9 from Howard Chu hyc@openldap.org --- Provided reproduction code is invalid, no further response.