-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ber scanf/printf. #51205
Fix ber scanf/printf. #51205
Conversation
4ac15ed
to
91fce13
Compare
@joperezr your idea of using OpenLdap specific functions looks promising, it is much easier to do then the native shim, however, I can't find how to encode If we want to stick to this solution we can do a few things:
I will try to code 2. tomorrow, if we don't extend API and don't allow the users to work with the BerElement directly it should work (otherwise we can lose a tag). |
Thank you so much for trying this other approach. I agree with your plan of attempting 2 and if that doesn't work then just going with 3 instead. To be honest we don't really use all of the encoding support fully as we mostly only have it to support the basic scenarios that the communication with ldap requires. We have good unit test coverage on the BerPal, and we have some tests that need to be rujn manually against an ldap server to ensure that the overall connection and manipulation of ldap still works as expected, so I can give you more details on how to run that too. |
/azp run runtime-libraries-coreclr outerloop, runtime-libraries-coreclr outerloop-osx |
Azure Pipelines successfully started running 2 pipeline(s). |
51bb400
to
46908e6
Compare
/azp run runtime-libraries-coreclr outerloop, runtime-libraries-coreclr outerloop-osx |
Azure Pipelines successfully started running 2 pipeline(s). |
The failures are due to #51346, I think this PR is ready for review. |
|
||
public static int ber_printf_tag(SafeBerHandle berElement, string format, int tag) | ||
{ | ||
return ber_default_successful_return_code; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a comment here saying why we are not supporting this? Or I wonder if for this scenario we should falk back to use the varargs func instead so that it works as expected on platforms where they are supported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a comment:
// Ber Linux tags are passed with the values that they affect, so this function does nothing.
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"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, could we just fall back to call the old printf in this case? I know it means that this won't work in the new Macs, but that means we won't regress existing runtimes in case support is added in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have supported 'v' on Linux (and changed the Windows version to be consistent) by converting one 'v' call to several 'o' calls:
Line 121 in 0711327
error = EncodingByteArrayHelper(berElement, tempValue, 'o', tag); |
it does not work for 'V' because I have not found an API that takes 'BerVal'.
The definition is:
V
Several octet strings. A null-terminated array of struct berval *'s is supplied. Note that a construct like '{V}' is required to get an actual SEQUENCE OF octet strings.
and there is no API that takes a single A null-terminated struct berval *'s
so the only thing that regressed is 'V' encoding for Linux. 't' (encoding, decoding), 'v'(encoding) are supported'; 'V' and 'v' decoding were not supported before these changes.
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"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decode for vv and VV was not supported previously so we don't regress anything here:
runtime/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs
Line 124 in acff8f3
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // vv and VV formats are not supported yet in Linux |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I understand that, but what I mean is imagine that in a future version of libldap (if it ever ships) they add support for vv or VV, then the old code would have just worked as the scanf calls would just light up and start working; whereas if we keep it the way you have it we would have to basically make the change manually. TBH I doubt libldap will ship a new future major version with this support so I'm fine keeping it as you have it but just wanted to raise the comment to get your opinion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this comment means that "vv" and "VV" are not supported in System.DirectoryServices.Protocols or in OpenLDAP? I thought it was about "System.DirectoryServices.Protocols". I guess it was not supported exactly because vararg calling convention for passing such struct was different so we could not call it even on x64 Unix.
...em.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs
Outdated
Show resolved
Hide resolved
|
||
valueCount++; | ||
} | ||
else if (fmt == 't') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure I'm missing something obvious but I'm not understanding why we mvoed the t here. even when unsupported seems to me we are doing sort of the same than we were doing before right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
't' means tag and it applies to the next thing in the string, there is no API that does this, like "ber_put_arg" or something, so I introduced a mechanism on C# side that saves the tag when we see it:
tag = (int)value[valueCount];
tagIsSet = true;
and then pass it to the next value, so the tags are kept working on Linux.
just as an overall comment, things look very good here and I'm happy to see that all of our ber unit tests are passing, but it would be good to run all of our scenario tests against an actual LDAP server before merging just in case. |
How could I do this? |
ping @joperezr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have ran the manual tests against Active Directory server in both Windows and Linux and they both passed just fine so I think we can go ahead and merge this.
Thanks a lot for the refactoring work @sandreenko! |
Thanks @joperezr for your help with it! |
This reverts commit f664348.
That is an alternative solution for #49105, instead of #50540.
OSX arm64 has a special calling convention for varargs so we can't rely on the old mechanism when we declared methods as non-varargs but the arguments went to the registers and stack slots that were expected by a native vararg callee.
For completeness, I do the change on all platforms so we don't rely on this behavior that is not guaranteed to work on new platforms/os in the future.
Use the vararg calling convention on Windows and non-vararg methods that are provided by OpenLDAP on Unix.