-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Add nullable annotations to System.DirectoryServices #48454
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
...raries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs
Show resolved
Hide resolved
...raries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs
Show resolved
Hide resolved
...raries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs
Show resolved
Hide resolved
...m.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryPartition.cs
Show resolved
Hide resolved
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.
Thanks @krwq i have 2 main comment:
- Most of the comments related to
PropertyManager.GetPropertyValue(...)
which if look closely does not return null so better to remove?
which saving many1
in many files - Most overrides of
OnInsertComplete(int index, object? value), OnRemoveComplete(int index, object? value), OnSetComplete(int index, object? oldValue, object? newValue)
are producing NRE if the value is null, i think we should suppress the warning instead making it nullable
Other than that overall LGTM.
@@ -144,7 +144,7 @@ public static AdamInstance GetAdamInstance(DirectoryContext context) | |||
{ | |||
throw new ActiveDirectoryObjectNotFoundException(SR.Format(SR.AINotFound, context.Name), typeof(AdamInstance), context.Name); | |||
} | |||
dnsHostName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName); | |||
dnsHostName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName)!; |
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.
Here and everywhere else PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName)
is not returning null, instead it throws
dnsHostName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName)!; | |
dnsHostName = (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName); |
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.
Note it will only throw if property value is not there at all but if null value is present it will not throw and return null instead. Also note that DirectoryEntry.Properties
(which this helper accesses) is public and while there is a code path guarding against null in DirectoryEntry.Properties[anyName].Value
(it's a no-op) then there is nothing guarding against DirectoryEntry.Properties[anyName].Add(null)
.
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.
You are right, the code is not guaranteeing against null, but somehow PropertyValueCollection[index] and PropertyValueCollection.Add(object value) both documented to be non null (it says it throws ANE for null value). Literally for all references we are suppressing the return value from (string)PropertyManager.GetPropertyValue(context, rootDSE, PropertyManager.DnsHostName)!
which also illustrates the intention was non-null
, there is something wrong here or we are missing something.
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.
With that being said I am resolving this and all comments related to this, please take a look at other unrelated comments
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.
there is nothing guarding against DirectoryEntry.Properties[anyName].Add(null)
Even it is allowing null I think setting it into null should be an error, not sure who is the expert in this area, I am OK leaving this nullable for this PR but i think we should file an issue for this
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.
...raries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs
Show resolved
Hide resolved
...ryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs
Show resolved
Hide resolved
src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs
Show resolved
Hide resolved
src/libraries/System.DirectoryServices/src/System/DirectoryServices/PropertyCollection.cs
Outdated
Show resolved
Hide resolved
...DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReadOnlySiteLinkCollection.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.DirectoryServices/src/System/DirectoryServices/DirectoryEntry.cs
Outdated
Show resolved
Hide resolved
@@ -195,7 +196,7 @@ public TimeSpan ClientTimeout | |||
/// Gets or sets the Lightweight Directory Access Protocol (LDAP) filter string format. | |||
/// </devdoc> | |||
[DefaultValue(defaultFilter)] | |||
public string Filter | |||
public string? Filter |
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 think it shouldn't be nullable as it has defaulted to non-null and the setter is allowing null but also defaulting if the value was null, it will never be null unless set to null by constructor which might be mistake
public string? Filter | |
[AllowNull] | |
public string Filter |
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've initially had it this way but this can currently be null (maybe due to bug, maybe intentional):
public DirectorySearcher(DirectoryEntry? searchRoot, string? filter, string[]? propertiesToLoad, SearchScope scope)
is assigning filter directly and does not do any validation- in Utils.cs:
internal static Hashtable GetValuesWithRangeRetrieval(DirectoryEntry searchRootEntry, string? filter, ArrayList propertiesWithRangeRetrieval, ArrayList propertiesWithoutRangeRetrieval, SearchScope searchScope)
is being called with explicit null from DirectoryServer.csGetParitions()
(call goes throughinternal static Hashtable GetValuesWithRangeRetrieval(DirectoryEntry searchRootEntry, string? filter, ArrayList propertiesToLoad, SearchScope searchScope)
)
I'll leave this open and turn this into an issue
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.
(likely constructor should assign to property rather than field)
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.
{ | ||
} | ||
|
||
/// <devdoc> | ||
/// Initializes a new instance of the <see cref='System.DirectoryServices.DirectorySearcher'/> class with the <see cref='System.DirectoryServices.DirectorySearcher.SearchRoot'/>, <see cref='System.DirectoryServices.DirectorySearcher.Filter'/>, <see cref='System.DirectoryServices.DirectorySearcher.PropertiesToLoad'/>, and <see cref='System.DirectoryServices.DirectorySearcher.SearchScope'/> properties set to the given | ||
/// values. | ||
/// </devdoc> | ||
public DirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad, SearchScope scope) | ||
public DirectorySearcher(DirectoryEntry? searchRoot, string? filter, string[]? propertiesToLoad, SearchScope scope) |
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.
Filter seems not expected to be nullable, it defaults with nonnull when not provided, the setter is allowing null but also defaulting if the value
was null, it might be an error if it is set to null by the constructor
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'll add this info to the issue above once I create it but I'd say it should handle the null given this never threw anything and there is an obvious value which should be used in place of null
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.
ddcafb6
to
4ff89aa
Compare
I've rebased since there was recently some change in DS |
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 only spot checked again, but what I saw LGTM.
(adjusted nullability of stuff deriving from CollectionBase based on offline conversation) |
Given it's already signed off, CI is passing, all issues are resolved/turned into issues and only changes made after the sign-off are what @buyaa-n recommended in the comment and @stephentoub has also confirmed in the offline conversation as a right path I'm merging this. |
No description provided.