-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Fix backslash escaping in Windows parameter files #31204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,21 +23,41 @@ private WindowsParamFileEscaper() {} | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** | ||||||||||||||||||||||
| * Escapes the @argument to be suitable for lld-link. Existing double-quotes are escaped, and | ||||||||||||||||||||||
| * arguments that contain whitespace are surrounded in unescaped double-quotes. | ||||||||||||||||||||||
| * empty arguments and arguments that contain whitespace are surrounded in unescaped | ||||||||||||||||||||||
| * double-quotes. Backslashes immediately before a double-quote are doubled. | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * @see <a | ||||||||||||||||||||||
| * href="https://github.com/llvm/llvm-project/blob/4bc3b3501ff994fb3504ed2b973342821a9c8cea/llvm/lib/Support/CommandLine.cpp#L916">LLVM | ||||||||||||||||||||||
| * Parser Implementation</a> | ||||||||||||||||||||||
| */ | ||||||||||||||||||||||
| public static String escapeString(String argument) { | ||||||||||||||||||||||
| boolean needsSurroundingQuotes = containsWhitespace(argument); | ||||||||||||||||||||||
| boolean needsSurroundingQuotes = argument.isEmpty() || containsWhitespace(argument); | ||||||||||||||||||||||
| StringBuilder out = new StringBuilder(); | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the thorough fix and tests — I verified that the new output round-trips correctly through LLVM's Windows tokenizer ( One perf consideration: Could we keep a fast path for those and pre-size the builder otherwise? Semantics are unchanged, since with no backslashes and no quotes the loop is a verbatim copy and the trailing-backslash handling is a no-op:
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks! Addressed both comments. |
||||||||||||||||||||||
| if (needsSurroundingQuotes) { | ||||||||||||||||||||||
| out.append("\""); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| out.append(argument.replace("\"", "\\\"")); | ||||||||||||||||||||||
| int backslashes = 0; | ||||||||||||||||||||||
| for (int i = 0; i < argument.length(); i++) { | ||||||||||||||||||||||
| char c = argument.charAt(i); | ||||||||||||||||||||||
| if (c == '\\') { | ||||||||||||||||||||||
| backslashes++; | ||||||||||||||||||||||
| continue; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| if (c == '"') { | ||||||||||||||||||||||
| // Each literal backslash needs a pair, followed by one to escape the quote. | ||||||||||||||||||||||
| out.append("\\".repeat(2 * backslashes + 1)); | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| out.append("\\".repeat(backslashes)); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| out.append(c); | ||||||||||||||||||||||
| backslashes = 0; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| if (needsSurroundingQuotes) { | ||||||||||||||||||||||
| // Keep trailing backslashes from escaping the closing quote. | ||||||||||||||||||||||
| out.append("\\".repeat(2 * backslashes)); | ||||||||||||||||||||||
| out.append("\""); | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| out.append("\\".repeat(backslashes)); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return out.toString(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating this javadoc. Could you also update the other copy of it that documents the same format for users?
ParameterFileType.WINDOWSinParameterFile.javastill describes the old behavior:Something like: