`{1~20,30}` printed the placeholder as is, because the `,end` part was only
checked when the start index was inside the string. `{1~20}` printed nothing.
Parse and check the whole range first, so that a valid range that lies outside
of the string gives an empty result.
Numbers that don't fit in 32 bits were truncated, so `{4294967297}` was read
as `{1}`, `{4294967296}` as the next argument, and `{$4294967297}` as the
first constant. The same applied to the start, end and length of `~`, `:`, `<`,
`>` and `|`. Clamp them instead, so that they stay out of range.
Also avoid negating INT32_MIN for the ellipsis length of `{1:-2147483648}`,
which is a signed integer overflow.
When a `{?arg}` / `{/arg}` conditional is skipped, the end of the skipped part
was the next `{?}` / `{/}` in the format string, even if it closed a
conditional nested in it. The text after the nested conditional was printed
and the real closing `{?}` / `{/}` was reported as an invalid placeholder.
A literal `{{?}}` inside the skipped part also ended it.
Skip to the `{?}` / `{/}` that matches the opening one, like the printing path
already does.
* Format: fix substring ends before the start of the string
Closes#2668
Signed-off-by: Don Yin <Don_Yin@outlook.com>
* Doc: moves changelog entry to Unreleased [ci skip]
I moved the unreleased fix out of the 2.70.0 section.
Signed-off-by: Don Yin <Don_Yin@outlook.com>
---------
Signed-off-by: Don Yin <Don_Yin@outlook.com>