Hi all,
While profiling LDAP lookup performance using Valgrind, I identified a
minor memory leak in `dict_ldap_vendor_version()` inside
`src/global/dict_ldap.c`.
When `dict_ldap_vendor_version()` queries LDAP API info via
`ldap_get_option(..., LDAP_OPT_API_INFO, &api)`, the OpenLDAP C API
internally allocates memory for `api.ldapai_vendor_name` and
`api.ldapai_extensions`. Currently, the function directly returns
`api.ldapai_vendor_version` without freeing these allocated pointers.
This is explicitly documented in the ldap_get_option(3) manual page:
"The caller is responsible for freeing the elements of the
ldapai_extensions array and the array itself using ldap_memfree(3). The
caller must also free the ldapi_vendor_name."
This patch stores `api.ldapai_vendor_version` in a temporary variable,
explicitly frees the allocated structures using `ldap_memfree()` and
`ldap_memvfree()`, and then returns the version value (C89 compliant).
Valgrind snippet BEFORE patch:
================================
=1370319== 165 (56 direct, 109 indirect) bytes in 1 blocks are definitely
lost in loss record 261 of 411
=1370319== at 0x4846828: malloc
=1370319== by 0x493BC35: ber_memalloc_x
=1370319== by 0x493C361: ber_strdup_x
=1370319== by 0x490367E: ldap_get_option
=1370319== by 0x11B595: dict_ldap_vendor_version (dict_ldap.c:248)
...
=1370319== LEAK SUMMARY:
=1370319== definitely lost: 65 bytes in 2 blocks
=1370319== indirectly lost: 109 bytes in 6 blocks
Valgrind snippet AFTER patch:
===============================
=1356656== LEAK SUMMARY:
=1356656== definitely lost: 0 bytes in 0 blocks
=1356656== indirectly lost: 0 bytes in 0 blocks
The patch is included inline below and also attached to this email to
prevent mail client formatting issues.
Best regards,
Pourya Adeli
---
src/global/dict_ldap.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/global/dict_ldap.c b/src/global/dict_ldap.c
index 1e65a51..a223b19 100644
--- a/src/global/dict_ldap.c
+++ b/src/global/dict_ldap.c
@@ -229,6 +229,7 @@ static int dict_ldap_vendor_version(void)
{
const char *myname = "dict_ldap_api_info";
LDAPAPIInfo api;
+ int vendor_version;
/*
* We tell the library our version, and it tells us its version and/or
@@ -247,7 +248,11 @@ static int dict_ldap_vendor_version(void)
msg_fatal("%s: run-time API vendor: %s, compiled with: %s",
myname, api.ldapai_vendor_name, LDAP_VENDOR_NAME);
- return (api.ldapai_vendor_version);
+ vendor_version = api.ldapai_vendor_version;
+ ldap_memfree(api.ldapai_vendor_name);
+ ldap_memvfree((void **) api.ldapai_extensions);
+
+ return (vendor_version);
}
From 863e16ad0edf2d5012e99f1340e1ee9e86c75d2d Mon Sep 17 00:00:00 2001
From: Pourya Adeli <[email protected]>
Date: Wed, 2 Sep 2026 20:11:03 +0330
Subject: [PATCH] Fix memory leak in dict_ldap_vendor_version
Explicitly free ldapai_vendor_name and ldapai_extensions allocated by OpenLDAP in dict_ldap_vendor_version().
---
src/global/dict_ldap.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/global/dict_ldap.c b/src/global/dict_ldap.c
index 1e65a51..a223b19 100644
--- a/src/global/dict_ldap.c
+++ b/src/global/dict_ldap.c
@@ -229,6 +229,7 @@ static int dict_ldap_vendor_version(void)
{
const char *myname = "dict_ldap_api_info";
LDAPAPIInfo api;
+ int vendor_version;
/*
* We tell the library our version, and it tells us its version and/or
@@ -247,7 +248,11 @@ static int dict_ldap_vendor_version(void)
msg_fatal("%s: run-time API vendor: %s, compiled with: %s",
myname, api.ldapai_vendor_name, LDAP_VENDOR_NAME);
- return (api.ldapai_vendor_version);
+ vendor_version = api.ldapai_vendor_version;
+ ldap_memfree(api.ldapai_vendor_name);
+ ldap_memvfree((void **) api.ldapai_extensions);
+
+ return (vendor_version);
}
/*
--
2.55.0
_______________________________________________
Postfix-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]