-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Fix Number.ParseNumber to not assume '\0' at the end of a span #17808
Conversation
This routine was written for parsing strings, which are implicitly null-terminated, and it doesn't factor in string length but instead uses tricks to exit loops when the next character is null. Now that the routine is also used for spans, this is very problematic, as spans need not be null terminated, and generally aren't when they represent slices, and expecting a null termination like this can result in walking off the end of valid memory. I would like to see all of this code rewritten to use span. In the interim, though, as a short-term fix I've changed all dereferences of the current position to compare against the length of the span (or, rather, a pointer to the end), and pretend that a null terminator was found if we've hit the end.
| while (true) | ||
| { | ||
| char cp = p < pEnd ? *p : '\0'; | ||
| if (cp != *str && (*str != '\u00a0' || cp != '\u0020')) |
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.
This is a case where I think !(*str == '\u00a0' && cp == '\u0020') would be much clearer.
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.
Ok.
danmoseley
left a comment
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.
Ugh...
|
In general, it is hard to prove the code in this file is safe by reading it. For example NumberBuffer is assumed to be null terminated above. And it seems it always is, but this is from several frames up, where the |
Yes, hence my comment about wanting to see all of this rewritten. But that's too big a change to make right now. |
…t#17808) * Fix Number.ParseNumber to not assume '\0' at the end of a span This routine was written for parsing strings, which are implicitly null-terminated, and it doesn't factor in string length but instead uses tricks to exit loops when the next character is null. Now that the routine is also used for spans, this is very problematic, as spans need not be null terminated, and generally aren't when they represent slices, and expecting a null termination like this can result in walking off the end of valid memory. I would like to see all of this code rewritten to use span. In the interim, though, as a short-term fix I've changed all dereferences of the current position to compare against the length of the span (or, rather, a pointer to the end), and pretend that a null terminator was found if we've hit the end. * Address PR feedback
… (#17820) * Fix Number.ParseNumber to not assume '\0' at the end of a span This routine was written for parsing strings, which are implicitly null-terminated, and it doesn't factor in string length but instead uses tricks to exit loops when the next character is null. Now that the routine is also used for spans, this is very problematic, as spans need not be null terminated, and generally aren't when they represent slices, and expecting a null termination like this can result in walking off the end of valid memory. I would like to see all of this code rewritten to use span. In the interim, though, as a short-term fix I've changed all dereferences of the current position to compare against the length of the span (or, rather, a pointer to the end), and pretend that a null terminator was found if we've hit the end. * Address PR feedback
@stephentoub do we need an issue to track this? I can't find one. |
|
I don't believe we have one. |
This routine was written for parsing strings, which are implicitly null-terminated, and it doesn't factor in string length but instead uses tricks to exit loops when the next character is null. Now that the routine is also used for spans, this is very problematic, as spans need not be null terminated, and generally aren't when they represent slices, and expecting a null termination like this can result in walking off the end of valid memory.
I would like to see all of this code rewritten to use span. In the interim, though, as a short-term fix I've changed all dereferences of the current position to compare against the length of the span (or, rather, a pointer to the end), and pretend that a null terminator was found if we've hit the end.
Contributes to https://github.com/dotnet/corefx/issues/29343
cc: @jkotas, @danmosemsft