Skip to content
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 incorrect string length calculation #76127

Merged
merged 3 commits into from
Sep 27, 2022
Merged

Fix incorrect string length calculation #76127

merged 3 commits into from
Sep 27, 2022

Conversation

Sparin
Copy link
Contributor

@Sparin Sparin commented Sep 24, 2022

Fixes #76125

ANSI string depends on system encoding charset. Unix's implementation of Marshal.StringToHGlobalAnsi encodes in UTF8. UTF8 characters which are out of 8-bit range (otcet) encodes in multiple bytes (otcets). ASCII characters usually are in 0x00-0x7F range but cyrillic and other characters are not. For example, 'Зфыы123;' (eq. 'Pass123$') will be encoded in 12 bytes instead of 8

Fix #76125
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Sep 24, 2022
@ghost
Copy link

ghost commented Sep 24, 2022

Tagging subscribers to this area: @dotnet/area-system-directoryservices, @jay98014
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #76125

Author: Sparin
Assignees: -
Labels:

area-System.DirectoryServices

Milestone: -

Comment on lines 178 to 194
internal static IntPtr StringToPtr(string s) => Marshal.StringToHGlobalAnsi(s);

internal static unsafe IntPtr StringToPtr(string s, out int length)
{
var pointer = StringToPtr(s);
length = 0;

if (pointer == IntPtr.Zero)
{
return pointer;
}

byte* stringPtr = (byte*)pointer;
while (stringPtr[length] != '\0')
{
length++;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If StringToPtr is not used elsewhere, you can shorten the method to this. Either way a while loop to find the NUL is not advised because it won't be vectorized.

Suggested change
internal static IntPtr StringToPtr(string s) => Marshal.StringToHGlobalAnsi(s);
internal static unsafe IntPtr StringToPtr(string s, out int length)
{
var pointer = StringToPtr(s);
length = 0;
if (pointer == IntPtr.Zero)
{
return pointer;
}
byte* stringPtr = (byte*)pointer;
while (stringPtr[length] != '\0')
{
length++;
}
internal static unsafe IntPtr StringToPtr(string s, out int length)
{
var pointer = Marshal.StringToHGlobalAnsi(s);
length = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pointer).Length;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I didn't know about this before. Applied this suggestion partly as a new commit.
Also, StringToPtr is used in other methods but they don't use string length. So that's why I added this overload with out int length

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing I thought is to not add this new overload and instead calculate the length at the callsite where it's needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like that? https://github.com/Sparin/runtime/commit/78484539924277e2295756616a639d1d55c14f95
Tell me if I should apply this commit to PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. It's up to you if you like it more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Seems cleaner now for me than the first one :D

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dotnet/area-system-directoryservices .NET 7 backport candidate?

@Sparin
Copy link
Contributor Author

Sparin commented Sep 27, 2022

Is it possible to re-run failed checks? It seems failed due to infrastructure performance

@jkotas
Copy link
Member

jkotas commented Sep 27, 2022

Thank you!

@jkotas jkotas merged commit 94c6fe6 into dotnet:main Sep 27, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Oct 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.DirectoryServices community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect string length calculation in LdapPal.Linux
3 participants