Skip to content

Commit

Permalink
Fix ber scanf/printf. (#51205)
Browse files Browse the repository at this point in the history
* Reenable the tests.

* Use __arglist for windows.

* Use ber_put_*/ber_get_* for Unix

* fix tag

* fix review.
  • Loading branch information
Sergey Andreenko authored Apr 28, 2021
1 parent 85e4aea commit f664348
Show file tree
Hide file tree
Showing 18 changed files with 267 additions and 78 deletions.
194 changes: 178 additions & 16 deletions src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
using System;
using System.Runtime.InteropServices;
using System.DirectoryServices.Protocols;
using System.Diagnostics;

internal static partial class Interop
{
internal static partial class Ldap
{
private const int ber_default_successful_return_code = 0;

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_alloc_t", CharSet = CharSet.Ansi)]
public static extern IntPtr ber_alloc(int option);

Expand All @@ -18,17 +21,105 @@ internal static partial class Ldap
[DllImport(Libraries.OpenLdap, EntryPoint = "ber_free", CharSet = CharSet.Ansi)]
public static extern IntPtr ber_free([In] IntPtr berelement, int option);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
public static extern int ber_printf_emptyarg(SafeBerHandle berElement, string format);
public static int ber_printf_emptyarg(SafeBerHandle berElement, string format, int tag)
{
if (format == "{")
{
return ber_start_seq(berElement, tag);
}
else if (format == "}")
{
return ber_put_seq(berElement, tag);
}
else if (format == "[")
{
return ber_start_set(berElement, tag);
}
else if (format == "]")
{
return ber_put_set(berElement, tag);
}
else
{
Debug.Assert(format == "n");
return ber_put_null(berElement, tag);
}
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_start_seq", CharSet = CharSet.Ansi)]
public static extern int ber_start_seq(SafeBerHandle berElement, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_start_set", CharSet = CharSet.Ansi)]
public static extern int ber_start_set(SafeBerHandle berElement, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_seq", CharSet = CharSet.Ansi)]
public static extern int ber_put_seq(SafeBerHandle berElement, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_set", CharSet = CharSet.Ansi)]
public static extern int ber_put_set(SafeBerHandle berElement, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_null", CharSet = CharSet.Ansi)]
public static extern int ber_put_null(SafeBerHandle berElement, int tag);


public static int ber_printf_tag(SafeBerHandle berElement, string format, int tag)
{
// Ber Linux tags are passed with the values that they affect, like `ber_printf_int(.., tag)`.
// So this function does nothing on Linux.
return ber_default_successful_return_code;
}

public static int ber_printf_int(SafeBerHandle berElement, string format, int value, int tag)
{
if (format == "i")
{
return ber_put_int(berElement, value, tag);
}
else if (format == "e")
{
return ber_put_enum(berElement, value, tag);
}
else
{
Debug.Assert(format == "b");
return ber_put_boolean(berElement, value, tag);
}
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_int", CharSet = CharSet.Ansi)]
public static extern int ber_put_int(SafeBerHandle berElement, int value, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_enum", CharSet = CharSet.Ansi)]
public static extern int ber_put_enum(SafeBerHandle berElement, int value, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value);
[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_boolean", CharSet = CharSet.Ansi)]
public static extern int ber_put_boolean(SafeBerHandle berElement, int value, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
public static extern int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length);
public static int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length, int tag)
{
if (format == "o")
{
return ber_put_ostring(berElement, value, length, tag);
}
else if (format == "s")
{
return ber_put_string(berElement, value, tag);
}
else
{
Debug.Assert(format == "X");
return ber_put_bitstring(berElement, value, length, tag);
}
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
public static extern int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value);
[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_ostring", CharSet = CharSet.Ansi)]
private static extern int ber_put_ostring(SafeBerHandle berElement, HGlobalMemHandle value, int length, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_string", CharSet = CharSet.Ansi)]
private static extern int ber_put_string(SafeBerHandle berElement, HGlobalMemHandle value, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_bitstring", CharSet = CharSet.Ansi)]
private static extern int ber_put_bitstring(SafeBerHandle berElement, HGlobalMemHandle value, int length, int tag);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_flatten", CharSet = CharSet.Ansi)]
public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value);
Expand All @@ -39,16 +130,87 @@ internal static partial class Ldap
[DllImport(Libraries.OpenLdap, EntryPoint = "ber_bvecfree", CharSet = CharSet.Ansi)]
public static extern int ber_bvecfree(IntPtr value);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
public static extern int ber_scanf(SafeBerHandle berElement, string format);
public static int ber_scanf_emptyarg(SafeBerHandle berElement, string format)
{
Debug.Assert(format == "{" || format == "}" || format == "[" || format == "]" || format == "n" || format == "x");
if (format == "{" || format == "[")
{
int len = 0;
return ber_skip_tag(berElement, ref len);
}
else if (format == "]" || format == "}")
{
return ber_default_successful_return_code;
}
else
{
Debug.Assert(format == "n" || format == "x");
return ber_get_null(berElement);
}
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_skip_tag", CharSet = CharSet.Ansi)]
private static extern int ber_skip_tag(SafeBerHandle berElement, ref int len);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_null", CharSet = CharSet.Ansi)]
private static extern int ber_get_null(SafeBerHandle berElement);

public static int ber_scanf_int(SafeBerHandle berElement, string format, ref int value)
{
if (format == "i")
{
return ber_get_int(berElement, ref value);
}
else if (format == "e")
{
return ber_get_enum(berElement, ref value);
}
else
{
Debug.Assert(format == "b");
return ber_get_boolean(berElement, ref value);
}
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_int", CharSet = CharSet.Ansi)]
private static extern int ber_get_int(SafeBerHandle berElement, ref int value);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_enum", CharSet = CharSet.Ansi)]
private static extern int ber_get_enum(SafeBerHandle berElement, ref int value);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_boolean", CharSet = CharSet.Ansi)]
private static extern int ber_get_boolean(SafeBerHandle berElement, ref int value);

public static int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength)
{
Debug.Assert(format == "B");
return ber_get_stringb(berElement, ref value, ref bitLength);
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_stringb", CharSet = CharSet.Ansi)]
private static extern int ber_get_stringb(SafeBerHandle berElement, ref IntPtr value, ref int bitLength);

public static int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value)
{
Debug.Assert(format == "O");
return ber_get_stringal(berElement, ref value);
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
public static extern int ber_scanf_int(SafeBerHandle berElement, string format, ref int value);
[DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_stringal", CharSet = CharSet.Ansi)]
private static extern int ber_get_stringal(SafeBerHandle berElement, ref IntPtr value);

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
public static extern int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength);
public static int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value, int tag)
{
Debug.Assert(format == "v" || format == "V");
// V and v are not supported on Unix yet.
return -1;
}

[DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value);
public static int ber_scanf_multibytearray(SafeBerHandle berElement, string format, ref IntPtr value)
{
Debug.Assert(format == "v" || format == "V");
// V and v are not supported on Unix yet.
return -1;
}
}
}
22 changes: 2 additions & 20 deletions src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,7 @@ internal static partial class Ldap
public static extern IntPtr ber_alloc(int option);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
public static extern int ber_printf_emptyarg(SafeBerHandle berElement, string format);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
public static extern int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
public static extern int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value);
public static extern int ber_printf(SafeBerHandle berElement, string format, __arglist);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)]
public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value);
Expand All @@ -34,16 +25,7 @@ internal static partial class Ldap
public static extern IntPtr ber_init(berval value);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
public static extern int ber_scanf(SafeBerHandle berElement, string format);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
public static extern int ber_scanf_int(SafeBerHandle berElement, string format, ref int value);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
public static extern int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength);
public static extern int ber_scanf(SafeBerHandle berElement, string format, __arglist);

[DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)]
public static extern int ber_bvfree(IntPtr value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,26 @@ internal static class BerPal

internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.Ldap.ber_flatten(berElement, ref flattenptr);

internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.Ldap.ber_printf_berarray(berElement, format, value);
internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value, int tag) => Interop.Ldap.ber_printf_berarray(berElement, format, value, tag);

internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.Ldap.ber_printf_bytearray(berElement, format, value, length);
internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length, int tag) => Interop.Ldap.ber_printf_bytearray(berElement, format, value, length, tag);

internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.Ldap.ber_printf_emptyarg(berElement, format);
internal static int PrintEmptyArgument(SafeBerHandle berElement, string format, int tag) => Interop.Ldap.ber_printf_emptyarg(berElement, format, tag);

internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.Ldap.ber_printf_int(berElement, format, value);
internal static int PrintInt(SafeBerHandle berElement, string format, int value, int tag) => Interop.Ldap.ber_printf_int(berElement, format, value, tag);

internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf(berElement, format);
internal static int PrintTag(SafeBerHandle berElement, string format, int tag) => Interop.Ldap.ber_printf_tag(berElement, format, tag);

internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf_emptyarg(berElement, format);

internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.Ldap.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength);

internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.Ldap.ber_scanf_int(berElement, format, ref result);

internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf_ptr(berElement, format, ref value);

internal static int ScanNextMultiByteArray(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf_multibytearray(berElement, format, ref value);

internal static bool IsBerDecodeError(int errorCode) => errorCode == -1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,25 @@ internal static class BerPal

internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.Ldap.ber_flatten(berElement, ref flattenptr);

internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.Ldap.ber_printf_berarray(berElement, format, value);
internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value, int tag) => Interop.Ldap.ber_printf(berElement, format, __arglist(value));

internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.Ldap.ber_printf_bytearray(berElement, format, value, length);
internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length, int tag) => Interop.Ldap.ber_printf(berElement, format, __arglist(value, length));

internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.Ldap.ber_printf_emptyarg(berElement, format);
internal static int PrintEmptyArgument(SafeBerHandle berElement, string format, int tag) => Interop.Ldap.ber_printf(berElement, format, __arglist());

internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.Ldap.ber_printf_int(berElement, format, value);
internal static int PrintInt(SafeBerHandle berElement, string format, int value, int tag) => Interop.Ldap.ber_printf(berElement, format, __arglist(value));

internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf(berElement, format);
internal static int PrintTag(SafeBerHandle berElement, string format, int tag) => Interop.Ldap.ber_printf(berElement, format, __arglist(tag));

internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.Ldap.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength);
internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf(berElement, format, __arglist());

internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.Ldap.ber_scanf_int(berElement, format, ref result);
internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref ptrResult, ref bitLength));

internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf_ptr(berElement, format, ref value);
internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref result));

internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref value));

internal static int ScanNextMultiByteArray(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref value));

internal static bool IsBerDecodeError(int errorCode) => errorCode != 0;
}
Expand Down
Loading

0 comments on commit f664348

Please sign in to comment.