diff --git a/native/WinProcessListHelper/WinProcessListHelper/main.cpp b/native/WinProcessListHelper/WinProcessListHelper/main.cpp index c21f9de2cbda..862b508539bf 100644 --- a/native/WinProcessListHelper/WinProcessListHelper/main.cpp +++ b/native/WinProcessListHelper/WinProcessListHelper/main.cpp @@ -4,9 +4,29 @@ using namespace std; #include #include +#include #pragma comment(lib, "wbemuuid.lib") +void stringReplaceAll(wstring& str, const wstring& oldStr, const wstring& newStr) +{ + int pos = 0; + while ((pos = str.find(oldStr, pos)) != string::npos) + { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } +} + +wstring escapeLineBreaks(const wstring& str) +{ + wstring result = str; + stringReplaceAll(result, L"\\", L"\\\\"); + stringReplaceAll(result, L"\n", L"\\n"); + stringReplaceAll(result, L"\r", L"\\r"); + return result; +} + int main(int argc, char **argv) { HRESULT hres; @@ -163,19 +183,19 @@ int main(int argc, char **argv) VARIANT vtId; pclsObj->Get(L"ProcessId", 0, &vtId, nullptr, nullptr); - wprintf_s(L"%d\n", vtId.intVal); + wcout << vtId.intVal << "\n"; VARIANT vtName; pclsObj->Get(L"Name", 0, &vtName, nullptr, nullptr); if (vtName.bstrVal != nullptr) - wprintf_s(L"%ls\n", vtName.bstrVal); + wcout << escapeLineBreaks(vtName.bstrVal) << L"\n"; else - wprintf_s(L"\n"); + wcout << L"\n"; VARIANT vtCmd; pclsObj->Get(L"CommandLine", 0, &vtCmd, nullptr, nullptr); if (vtCmd.bstrVal != nullptr) - wprintf_s(L"%ls\n", vtCmd.bstrVal); + wcout << L"\"" << escapeLineBreaks(vtCmd.bstrVal) << L"\"\n"; else - wprintf_s(L"\n"); + wcout << L"\"\"\n"; VariantClear(&vtId); VariantClear(&vtName); VariantClear(&vtCmd); diff --git a/platform/platform-util-io/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-util-io/src/com/intellij/execution/process/impl/ProcessListUtil.java index d800ea913a62..174d13ab3056 100644 --- a/platform/platform-util-io/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-util-io/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -266,6 +266,46 @@ public final class ProcessListUtil { return parseCommandOutput(Collections.singletonList(exeFile.getAbsolutePath()), ProcessListUtil::parseWinProcessListHelperOutput); } + @Nullable + private static String unescapeString(String str, boolean quoted) { + StringBuilder builder = new StringBuilder(); + if (quoted) { + str = str.substring(1, str.length() - 1); + } + for (int index = 0; index < str.length(); index++) { + if (str.charAt(index) == '\\') { + if (index == str.length() - 1) { + LOG.info("Invalid escaped string: backslash at the last position"); + LOG.debug(str); + return null; + } + switch (str.charAt(index + 1)) { + case '\\': { + builder.append('\\'); + break; + } + case 'n': { + builder.append('\n'); + break; + } + case 'r': { + builder.append('\r'); + break; + } + default: { + LOG.info("Invalid character after an escape symbol: " + str.charAt(index + 1)); + LOG.debug(str); + return null; + } + } + index++; + continue; + } + builder.append(str.charAt(index)); + } + return builder.toString(); + } + @Nullable static List parseWinProcessListHelperOutput(@NotNull String output) { String[] lines = StringUtil.splitByLines(output, false); @@ -286,10 +326,20 @@ public final class ProcessListUtil { } if (id == 0) continue; - String name = lines[offset + 1]; + String name = unescapeString(lines[offset + 1], false); + if (name == null) { + LOG.info("Invalid escaped name: " + lines[offset + 1]); + LOG.debug(output); + return null; + } if (StringUtil.isEmpty(name)) continue; - String commandLine = lines[offset + 2]; + String commandLine = unescapeString(lines[offset + 2], true); + if (commandLine == null) { + LOG.info("Invalid escaped command line: " + lines[offset + 2]); + LOG.debug(output); + return null; + } String args; if (commandLine.isEmpty()) { commandLine = name;