From b9b0610215a3e04ba39c68a666927319596a3e79 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 6 Apr 2023 20:00:56 +0200 Subject: [PATCH] GetQuotedString() uses correct windows cmdline notation - escaping of backslash and quotes - fixes gh-312 for new cmdline parser algorithm (gh-307, gh-310) Signed-off-by: Sergey G. Brester Reviewed-by: Tino Reichardt --- CPP/7zip/UI/Explorer/ContextMenu.cpp | 3 ++- CPP/Common/MyString.cpp | 38 ++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 77337f4d..153b2ebc 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -408,7 +408,8 @@ static UString GetQuotedReducedString(const UString &s) UString s2 = s; ReduceString(s2); s2.Replace(L"&", L"&&"); - return GetQuotedString(s2); + s2.InsertAtFront(L'"'); s2 += L'"'; // quote without GetQuotedString (because it escapes now) + return s2; } static void MyFormatNew_ReducedName(UString &s, const UString &name) diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index d9a857c8..8344418c 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -1806,10 +1806,44 @@ FString us2fs(const wchar_t *s) // ---------------------------------------- -UString GetQuotedString(const UString &s) +UString GetQuotedString(const UString &src) { UString s2 ('\"'); - s2 += s; + unsigned bcount = 0; + wchar_t c; const wchar_t *f = src.Ptr(), *s = f, *b = f; + // add string considering backslashes before quote (escape them): + while (1) + { + c = *s++; + switch (c) + { + case L'\\': + // a backslash - save the position and count them up to quote-char or regular char + if (!bcount) b = s-1; + bcount++; + break; + case L'\0': + // end of string (it is always quoted, so need to escape backslashes too): + case L'"': + // add part before backslash (and unescaped backslashes if some are there): + s2.AddFrom(f, (unsigned)(s - f - 1)); + f = s; + if (bcount) { + // escape backslashes before quote (same count of BS again): + s2.AddFrom(b, (unsigned)(s - b - 1)); + } + // done if end of string + if (c == L'\0') goto done; + // escape this quote char: + s2 += L"\\\""; + break; + default: + // a regular character, reset backslash counter + bcount = 0; + } + } + s2.AddFrom(f, (unsigned)(s - f - 1)); +done: s2 += '\"'; return s2; }