From 7f2faa7e9b7bc478dd04500b5c3b12530bdb59d4 Mon Sep 17 00:00:00 2001 From: arxhr007 Date: Sat, 31 Oct 2026 15:04:09 +0530 Subject: [PATCH] Format: fixes substring with an end index outside of the string `{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. --- CHANGELOG.md | 1 + src/common/impl/format.c | 23 +++++++++++++++-------- tests/format.c | 4 ++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f32a63369b..5523786664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Bugfixes: * Fixed substring formatting returning the remaining string when a negative end index is before the start of the string. (General) * Fixed a skipped `{?}` / `{/}` conditional in a format string ending at the `{?}` / `{/}` of a conditional nested in it. (General) * Fixed numbers in format strings that don't fit in 32 bits wrapping around to a valid argument index, constant index, substring index or length, e.g. `{4294967297}` being read as `{1}`, and a signed integer overflow for `{1:-2147483648}`. (General) +* Fixed substring formatting printing the placeholder as is, instead of nothing, when the start index is outside of the string and an end index is given. (General) Logos: * Added Tiny Core Linux (#2655) diff --git a/src/common/impl/format.c b/src/common/impl/format.c index 3fdae18e66..2c7f50a49c 100644 --- a/src/common/impl/format.c +++ b/src/common/impl/format.c @@ -592,15 +592,22 @@ static bool parseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint3 char* pEnd = nullptr; int32_t start = strToInt32(pSep + 1, &pEnd); - if (start < 0) { - start = (int32_t) tempString.length + start; + bool hasEnd = *pEnd == ','; + int32_t end = 0; + if (hasEnd) { + end = strToInt32(pEnd + 1, &pEnd); } - if (start >= 0 && (uint32_t) start < tempString.length) { - if (*pEnd == '\0') { - ffStrbufAppendNS(buffer, tempString.length - (uint32_t) start, &tempString.chars[start]); - } else if (*pEnd == ',') { - int32_t end = strToInt32(pEnd + 1, &pEnd); - if (!*pEnd) { + + // Check the whole range before using it, so that a valid range that lies + // outside of the string gives an empty result instead of an invalid placeholder + if (!*pEnd) { + if (start < 0) { + start = (int32_t) tempString.length + start; + } + if (start >= 0 && (uint32_t) start < tempString.length) { + if (!hasEnd) { + ffStrbufAppendNS(buffer, tempString.length - (uint32_t) start, &tempString.chars[start]); + } else { if (end < 0) { end = (int32_t) tempString.length + end; } diff --git a/tests/format.c b/tests/format.c index 223054075f..4e3e27bcbd 100644 --- a/tests/format.c +++ b/tests/format.c @@ -113,6 +113,10 @@ int main(void) { VERIFY("output({1~-5,-3})", "12345 67890", "output(67)"); VERIFY("output({1~-0,10})", "12345 67890", "output(12345 6789)"); VERIFY("output({1~-3,-5})", "12345 67890", "output()"); + VERIFY("output({1~11,12})", "12345 67890", "output()"); // Same as {1~11} + VERIFY("output({1~20,30})", "12345 67890", "output()"); // Same as {1~20} + VERIFY("output({1~-50,3})", "12345 67890", "output()"); // Same as {1~-50} + VERIFY("output({1~-50,-1})", "12345 67890", "output()"); // Same as {1~-50} VERIFY("output({1~})", "12345 67890", "output(12345 67890)"); // Same as {1~0} VERIFY("output({1~-0})", "12345 67890", "output(12345 67890)"); // Same as {1~0} VERIFY("output({1~,-1})", "12345 67890", "output(12345 6789)"); // Same as {1~0,-1}