Skip to content

Commit 34a42e4

Browse files
SAMI_DANIEL_SANTOS_SILVASAMI_DANIEL_SANTOS_SILVA
authored andcommitted
Fix BinarySearch logic
Updated the BinarySearch method in PrefixContainer to ensure that an exact match of a prefix does not incorrectly qualify as a valid prefix. Enhanced comments to clarify the flow and decision-making process when checking for delimiters. This change improves the accuracy of prefix matching for hierarchical key structures.
1 parent 3da6a69 commit 34a42e4

File tree

1 file changed

+31
-23
lines changed

1 file changed

+31
-23
lines changed

src/Mvc/Mvc.Core/src/ModelBinding/PrefixContainer.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -201,32 +201,40 @@ private int BinarySearch(string prefix)
201201
{
202202
Debug.Assert(candidate.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
203203

204-
// Okay, now we have a candidate that starts with the prefix. If the candidate is longer than
205-
// the prefix, we need to look at the next character and see if it's a delimiter.
206-
if (candidate.Length == prefix.Length)
207-
{
208-
// Exact match
209-
return pivot;
210-
}
211-
212-
var c = candidate[prefix.Length];
213-
if (c == '.' || c == '[')
204+
// At this point, we have identified a candidate that starts with the given prefix.
205+
// If the candidate's length is greater than that of the prefix, we need to examine
206+
// the character that immediately follows the prefix in the candidate string.
207+
// This step is crucial to determine if the candidate is a valid prefix match.
208+
// A valid prefix match occurs if the next character is either a delimiter ('.' or '['),
209+
// indicating that the candidate is a sub-key of the prefix. If the next character
210+
// is not a delimiter, it means the candidate contains additional characters that
211+
// extend beyond the prefix without forming a valid hierarchical relationship,
212+
// which should not qualify as a prefix match. Therefore, we will continue searching
213+
// for valid matches in this case.
214+
215+
if (candidate.Length > prefix.Length)
214216
{
215-
// Match, followed by delimiter
216-
return pivot;
217+
var c = candidate[prefix.Length];
218+
if (c == '.' || c == '[')
219+
{
220+
// Match, followed by delimiter
221+
return pivot;
222+
}
223+
224+
// Okay, so the candidate has some extra text. We need to keep searching.
225+
//
226+
// Can often assume the candidate string is greater than the prefix e.g. that works for
227+
// prefix: product
228+
// candidate: productId
229+
// most of the time because "product", "product.id", etc. will sort earlier than "productId". But,
230+
// the assumption isn't correct if "product[0]" is also in _sortedValues because that value will
231+
// sort later than "productId".
232+
//
233+
// Fall back to brute force and cover all the cases.
234+
return LinearSearch(prefix, start, end);
217235
}
218236

219-
// Okay, so the candidate has some extra text. We need to keep searching.
220-
//
221-
// Can often assume the candidate string is greater than the prefix e.g. that works for
222-
// prefix: product
223-
// candidate: productId
224-
// most of the time because "product", "product.id", etc. will sort earlier than "productId". But,
225-
// the assumption isn't correct if "product[0]" is also in _sortedValues because that value will
226-
// sort later than "productId".
227-
//
228-
// Fall back to brute force and cover all the cases.
229-
return LinearSearch(prefix, start, end);
237+
return -1;
230238
}
231239

232240
if (compare > 0)

0 commit comments

Comments
 (0)