Fail if Append()ing string to Rope in excess of TInlineString size #155
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Something like what’s in the patch in this PR would’ve prevented the problem introduced in #152 and reported in #153.
The problem is: the
Append()
method for Ropes allows passing in either a string or a pointer to a string. And in the case where a string is passed in, the runtime silently truncates the string if it exceeds a certain length (UTF8InlineSize
, which in practice seems to be 15). But when instead a pointer to a string is passed in, it doesn’t matter how long the string is.The intent of allowing strings to be passed to
Append()
seems to have been just for very short string constants. So we really shouldn’t useAppend()
with strings other than constants; we should instead always pass in pointers to strings.So the initial patch in this PR causes Wattsi to fail with an error if the string passed in would end up being truncated, and emits a message suggesting to instead call
Append()
with a string pointer.The patch is inelegant, and someone with better familiarity with Pascal could probably find a more-clever way. But as far as I know, in the
Rope.Append(const NewString: RopeInternals.TInlineString)
procedure itself, we can’t check if the length of the original string passed toAppend()
exceeds theTInlineString
type size,UTF8InlineSize
.We can’t check there because the runtime truncates the original string to the
TInlineString
type size whenAppend()
is called. So if the length of the original string exceeds the size of theTInlineString
type —UTF8InlineSize
— then the length ofNewString
will be the length of the truncated string (truncated down toUTF8InlineSize
).So this existing assert:
wattsi/src/lib/ropes.pas
Line 965 in 4cabebb
…will never work unless we allow the size of
TInlineString
to be greater thanUTF8InlineSize
(as the initial patch in this PR does) — because otherwise,NewString
will always be less than or equal toUTF8InlineSize
; that’s because, ifNewString
comes from a string whose length is greater thanUTF8InlineSize
(the size of theTInlineString
type), the runtime will always truncate it down toUTF8InlineSize
.So the initial patch in this PR allows the size of the
TInlineString
type to beUTF8InlineSize + 1
, but then fails/exits with an error message ifAppend()
is called with a string bigger thanUTF8InlineSize
.Because
Append()
is the only place whereTInlineString
is ever used in the existing code, this seems safe.