Skip to content

Commit

Permalink
Fix memory leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
BalassaMarton committed Jun 7, 2023
1 parent 2a92a62 commit f062358
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 132 deletions.
43 changes: 22 additions & 21 deletions LdapForNet/BerConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,8 @@ private static int BerScanfBitString(BerSafeHandle berElement, char fmt, out obj
byte[] byteArray = null;
var rc = LdapNative.Instance.ber_scanf_bitstring(berElement, new string(fmt, 1), ref ptrResult, ref length);

// try
// {
try
{
if (rc != -1)
{
if (ptrResult != IntPtr.Zero)
Expand All @@ -525,14 +525,14 @@ private static int BerScanfBitString(BerSafeHandle berElement, char fmt, out obj

result = byteArray;
}
// }
// finally
// {
// if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && ptrResult != IntPtr.Zero)
// {
// LdapNative.Instance.ber_memfree(ptrResult);
// }
// }
}
finally
{
if (ptrResult != IntPtr.Zero)
{
LdapNative.Instance.BerScanfFree(fmt, ptrResult);
}
}

return rc;
}
Expand Down Expand Up @@ -582,7 +582,7 @@ private static int BerScanfaString(BerSafeHandle berElement, char fmt, out objec
{
if (result != IntPtr.Zero)
{
LdapNative.Instance.ber_memfree(result);
LdapNative.Instance.BerScanfFree(fmt, result);
}
}

Expand All @@ -591,12 +591,12 @@ private static int BerScanfaString(BerSafeHandle berElement, char fmt, out objec
private static int BerScanfString(BerSafeHandle berElement, char fmt, out object result)
{
int rc;
var ptr = Marshal.AllocHGlobal(IntPtr.Size);
var ptr = IntPtr.Zero;
var length = -1;
result = null;
try
{
rc = LdapNative.Instance.ber_scanf_string(berElement, new string(fmt, 1), ptr, ref length);
rc = LdapNative.Instance.ber_scanf_string(berElement, new string(fmt, 1), ref ptr, ref length);
if (rc != -1)
{
var byteArray = new byte[length];
Expand All @@ -608,7 +608,7 @@ private static int BerScanfString(BerSafeHandle berElement, char fmt, out object
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
LdapNative.Instance.BerScanfFree(fmt, ptr);
}
}

Expand Down Expand Up @@ -688,11 +688,11 @@ private static int EncodingByteArrayHelper(BerSafeHandle berElement, byte[] valu

private static int DecodingBerValOstringHelper(BerSafeHandle berElement, char fmt, out byte[] byteArray)
{
var result = Marshal.AllocHGlobal(IntPtr.Size);
var result = IntPtr.Zero;
var binaryValue = new Native.Native.berval();
byteArray = null;

var error = LdapNative.Instance.ber_scanf_ostring(berElement, new string(fmt, 1), result);
var error = LdapNative.Instance.ber_scanf_ostring(berElement, new string(fmt, 1), ref result);

try
{
Expand All @@ -708,7 +708,7 @@ private static int DecodingBerValOstringHelper(BerSafeHandle berElement, char fm
{
if (result != IntPtr.Zero)
{
LdapNative.Instance.ber_memfree(result);
LdapNative.Instance.BerScanfFree(fmt, result);
}
}

Expand Down Expand Up @@ -742,7 +742,7 @@ private static int DecodingBerValByteArrayHelper(BerSafeHandle berElement, char
{
if (result != IntPtr.Zero)
{
LdapNative.Instance.ber_bvfree(result);
LdapNative.Instance.BerScanfFree(fmt, result);
}
}

Expand Down Expand Up @@ -771,6 +771,7 @@ private static int EncodingBerValHelper(BerSafeHandle berElement, byte[] value,
}
return rc;
}

private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[][] value, char fmt)
{
var stringArray = IntPtr.Zero;
Expand Down Expand Up @@ -947,7 +948,7 @@ private static int DecodingBerValMultiByteArrayHelper(BerSafeHandle berElement,
{
if (ptrResult != IntPtr.Zero)
{
LdapNative.Instance.ber_bvecfree(ptrResult);
LdapNative.Instance.BerScanfFree(fmt, ptrResult);
}
}

Expand Down Expand Up @@ -989,7 +990,7 @@ private static int DecodingBerValMultiByteArrayHelperW(BerSafeHandle berElement,
{
if (ptrResult != IntPtr.Zero)
{
//LdapNative.Instance.ber_bvarrayfree(ptrResult);
LdapNative.Instance.BerScanfFree(fmt, ptrResult);
}
}

Expand Down Expand Up @@ -1019,7 +1020,7 @@ private static int DecodingMultiByteArrayHelper(BerSafeHandle berElement, char f
{
if (ptrResult != IntPtr.Zero)
{
LdapNative.Instance.ber_memfree(ptrResult);
LdapNative.Instance.BerScanfFree(fmt, ptrResult);
}
}

Expand Down
122 changes: 71 additions & 51 deletions LdapForNet/LdapConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,31 +111,41 @@ public async Task BindAsync(Native.Native.LdapAuthType authType, LdapCredential
_native.LdapConnect(_ld, _connectionTimeOut);
var timeout = GetConnectionTimeval();
var result = IntPtr.Zero;
if (authType == Native.Native.LdapAuthType.Simple)
{
result = await _native.BindSimpleAsync(_ld, ldapCredential.UserName, ldapCredential.Password, timeout);
}
else if (authType == Native.Native.LdapAuthType.Anonymous)
{
result = await _native.BindSimpleAsync(_ld, null, null, timeout);
}
else if (authType == Native.Native.LdapAuthType.ExternalAd)
{
// no action required
}
else if (authType != Native.Native.LdapAuthType.Unknown)
try
{
result = await _native.BindSaslAsync(_ld, authType, ldapCredential, timeout);
}
else
{
throw new LdapAuthMethodNotSupportedException(
new LdapExceptionData($"Not implemented mechanism: {authType.ToString()}. Available: {Native.Native.LdapAuthType.Simple.ToString()} | {Native.Native.LdapAuthType.GssApi}. "));
if (authType == Native.Native.LdapAuthType.Simple)
{
result = await _native.BindSimpleAsync(_ld, ldapCredential.UserName, ldapCredential.Password, timeout);
}
else if (authType == Native.Native.LdapAuthType.Anonymous)
{
result = await _native.BindSimpleAsync(_ld, null, null, timeout);
}
else if (authType == Native.Native.LdapAuthType.ExternalAd)
{
// no action required
}
else if (authType != Native.Native.LdapAuthType.Unknown)
{
result = await _native.BindSaslAsync(_ld, authType, ldapCredential, timeout);
}
else
{
throw new LdapAuthMethodNotSupportedException(
new LdapExceptionData($"Not implemented mechanism: {authType.ToString()}. Available: {Native.Native.LdapAuthType.Simple.ToString()} | {Native.Native.LdapAuthType.GssApi}. "));
}

if (result != IntPtr.Zero)
{
ThrowIfParseResultError(result);
}
}

if (result != IntPtr.Zero)
finally
{
ThrowIfParseResultError(result);
if (result != IntPtr.Zero)
{
_native.ldap_msgfree(result);
}
}

_bound = true;
Expand Down Expand Up @@ -347,7 +357,6 @@ private DirectoryResponse ProcessResponse(DirectoryRequest directoryRequest,
CancellationToken token)
{
var status = LdapResultCompleteStatus.Unknown;
var msg = Marshal.AllocHGlobal(IntPtr.Size);

var timeout = GetConnectionTimeval();

Expand All @@ -357,39 +366,50 @@ private DirectoryResponse ProcessResponse(DirectoryRequest directoryRequest,
DirectoryResponse response = default;
while (status != LdapResultCompleteStatus.Complete && !token.IsCancellationRequested)
{
var msg = IntPtr.Zero;
var resType = _native.ldap_result(_ld, messageId, 0, timeout, ref msg);
ThrowIfResultError(directoryRequest, resType, response);

status = requestHandler.Handle(_ld, resType, msg, out response);
response.MessageId = messageId;

if (status == LdapResultCompleteStatus.Unknown)
try
{
throw new LdapException(new LdapExceptionData($"Unknown search type {resType}", nameof(_native.ldap_result), 1){ Response = response});
ThrowIfResultError(directoryRequest, resType, response);

status = requestHandler.Handle(_ld, resType, msg, out response);
response.MessageId = messageId;

if (status == LdapResultCompleteStatus.Unknown)
{
throw new LdapException(new LdapExceptionData($"Unknown search type {resType}", nameof(_native.ldap_result), 1){ Response = response});
}

if (status == LdapResultCompleteStatus.Complete)
{
var responseReferral = new Uri[0];
var responseControl = new DirectoryControl[0];
var res = ParseResultError(msg, out var errorMessage, out var matchedDn, ref responseReferral, ref responseControl);

if (res == (int)Native.Native.ResultCode.SizeLimitExceeded
&& directoryRequest is SearchRequest searchRequest
&& response is SearchResponse searchResponse
&& searchRequest.SizeLimit != 0
&& searchResponse.Entries.Count >= searchRequest.SizeLimit)
{
Debug.WriteLine("ldap_parse_result returned ResultCode.SizeLimitExceeded but the correct number of entries were already returned");
res = (int)Native.Native.ResultCode.Success;
errorMessage = null;
}

response.ResultCode = (Native.Native.ResultCode)res;
response.ErrorMessage = errorMessage;
response.Referral = responseReferral;
response.Controls = responseControl;
response.MatchedDN = matchedDn;
}
}

if (status == LdapResultCompleteStatus.Complete)
finally
{
var responseReferral = new Uri[0];
var responseControl = new DirectoryControl[0];
var res = ParseResultError(msg, out var errorMessage, out var matchedDn, ref responseReferral, ref responseControl);

if (res == (int)Native.Native.ResultCode.SizeLimitExceeded
&& directoryRequest is SearchRequest searchRequest
&& response is SearchResponse searchResponse
&& searchRequest.SizeLimit != 0
&& searchResponse.Entries.Count >= searchRequest.SizeLimit)
if (msg != IntPtr.Zero)
{
Debug.WriteLine("ldap_parse_result returned ResultCode.SizeLimitExceeded but the correct number of entries were already returned");
res = (int)Native.Native.ResultCode.Success;
errorMessage = null;
_native.ldap_msgfree(msg);
}

response.ResultCode = (Native.Native.ResultCode)res;
response.ErrorMessage = errorMessage;
response.Referral = responseReferral;
response.Controls = responseControl;
response.MatchedDN = matchedDn;
}
}

Expand Down Expand Up @@ -457,7 +477,7 @@ private int ParseResultError(IntPtr msg, out string errorMessage, out string mat
var referrals = IntPtr.Zero;
var serverctrls = IntPtr.Zero;
_native.ThrowIfError(_ld, _native.ldap_parse_result(_ld, msg, ref rc, ref matchedDnPtr, ref errorMessagePtr,
ref referrals, ref serverctrls, 1), nameof(_native.ldap_parse_result));
ref referrals, ref serverctrls, 0), nameof(_native.ldap_parse_result));
errorMessage = Encoder.Instance.PtrToString(errorMessagePtr);
matchedDn = Encoder.Instance.PtrToString(matchedDnPtr);
if (referrals != IntPtr.Zero)
Expand Down
9 changes: 6 additions & 3 deletions LdapForNet/Native/LdapNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ internal abstract int Search(SafeHandle ld, string @base, int scope, string filt
internal abstract LdapResultType ldap_result(SafeHandle ld, int msgid, int all, LDAP_TIMEVAL timeout,
ref IntPtr pMessage);


internal abstract int ldap_parse_result(SafeHandle ld, IntPtr result, ref int errcodep, ref IntPtr matcheddnp,
ref IntPtr errmsgp, ref IntPtr referralsp, ref IntPtr serverctrlsp, int freeit);

Expand Down Expand Up @@ -140,19 +141,21 @@ internal abstract int ldap_start_tls_s(SafeHandle ld, ref int serverReturnValue,
internal abstract int ber_peek_tag(SafeHandle berElement, ref int length);

internal abstract int ber_scanf_ptr(SafeHandle berElement, string format, ref IntPtr value);
internal abstract int ber_scanf_ostring(SafeHandle berElement, string format, IntPtr value);
internal abstract int ber_scanf_ostring(SafeHandle berElement, string format, ref IntPtr value);

internal abstract int ber_scanf_string(SafeHandle berElement, string format, IntPtr value, ref int length);
internal abstract int ber_scanf_string(SafeHandle berElement, string format, ref IntPtr value, ref int length);
internal abstract int ber_scanf_bitstring(SafeHandle berElement, string format, ref IntPtr value, ref int length);

internal abstract int ber_bvfree(IntPtr value);

internal abstract int ber_bvecfree(IntPtr value);

internal abstract IntPtr ber_free([In] IntPtr berelement, int option);
internal abstract IntPtr ber_free(IntPtr berelement, int option);
internal abstract void ber_memfree(IntPtr value);

internal abstract bool BerScanfSupports(char fmt);

internal abstract void BerScanfFree(char fmt, IntPtr ptr);

internal void ThrowIfError(int res, string method, IDictionary<string,string> details = default)
{
Expand Down
Loading

0 comments on commit f062358

Please sign in to comment.