diff options
author | 2016-06-17 15:17:37 +0000 | |
---|---|---|
committer | 2016-06-20 09:34:27 +0000 | |
commit | 4489aaf97cfe4dfbf904ecdcbf46b76f00f6b5b1 (patch) | |
tree | b886717a9f3ad6fc7aab9f1ca8c74b68138d5b90 /src | |
parent | 9cf9300d667b8b5671077c73bc29b4803c95c340 (diff) |
Correctly escape backslashes in proto messarges.
--
MOS_MIGRATED_REVID=125166943
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java | 37 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java | 3 |
2 files changed, 24 insertions, 16 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java index 6a8710189f..60483dafe1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java @@ -91,6 +91,7 @@ import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.syntax.Type.ConversionException; import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; +import com.google.protobuf.TextFormat; import java.util.List; import java.util.Map; @@ -715,25 +716,27 @@ public class SkylarkRuleClassFunctions { private static final BuiltinFunction toProto = new BuiltinFunction("to_proto") { public String invoke(SkylarkClassObject self, Location loc) throws EvalException { StringBuilder sb = new StringBuilder(); - printTextMessage(self, sb, 0, loc); + printProtoTextMessage(self, sb, 0, loc); return sb.toString(); } - private void printTextMessage(ClassObject object, StringBuilder sb, + private void printProtoTextMessage(ClassObject object, StringBuilder sb, int indent, Location loc) throws EvalException { for (String key : object.getKeys()) { - printTextMessage(key, object.getValue(key), sb, indent, loc); + printProtoTextMessage(key, object.getValue(key), sb, indent, loc); } } - private void printSimpleTextMessage(String key, Object value, StringBuilder sb, + private void printProtoTextMessage(String key, Object value, StringBuilder sb, int indent, Location loc, String container) throws EvalException { if (value instanceof ClassObject) { print(sb, key + " {", indent); - printTextMessage((ClassObject) value, sb, indent + 1, loc); + printProtoTextMessage((ClassObject) value, sb, indent + 1, loc); print(sb, "}", indent); } else if (value instanceof String) { - print(sb, key + ": \"" + escapeString((String) value) + "\"", indent); + print(sb, + key + ": \"" + escapeDoubleQuotesAndBackslashesAndNewlines((String) value) + "\"", + indent); } else if (value instanceof Integer) { print(sb, key + ": " + value, indent); } else if (value instanceof Boolean) { @@ -747,16 +750,16 @@ public class SkylarkRuleClassFunctions { } } - private void printTextMessage(String key, Object value, StringBuilder sb, + private void printProtoTextMessage(String key, Object value, StringBuilder sb, int indent, Location loc) throws EvalException { if (value instanceof SkylarkList) { for (Object item : ((SkylarkList) value)) { // TODO(bazel-team): There should be some constraint on the fields of the structs // in the same list but we ignore that for now. - printSimpleTextMessage(key, item, sb, indent, loc, "list element in struct field"); + printProtoTextMessage(key, item, sb, indent, loc, "list element in struct field"); } } else { - printSimpleTextMessage(key, value, sb, indent, loc, "struct field"); + printProtoTextMessage(key, value, sb, indent, loc, "struct field"); } } @@ -769,10 +772,13 @@ public class SkylarkRuleClassFunctions { } }; - // Escapes the given string for use in Proto messages or JSON strings. - private static String escapeString(String string) { - // TODO(bazel-team): use guava's SourceCodeEscapers when it's released. - return string.replace("\"", "\\\"").replace("\n", "\\n"); + /** + * Escapes the given string for use in proto/JSON string. + * + * <p>This escapes double quotes, backslashes, and newlines. + */ + private static String escapeDoubleQuotesAndBackslashesAndNewlines(String string) { + return TextFormat.escapeDoubleQuotesAndBackslashes(string).replace("\n", "\\n"); } @SkylarkSignature(name = "to_json", @@ -846,9 +852,8 @@ public class SkylarkRuleClassFunctions { } private String jsonEscapeString(String string) { - return escapeString(string.replace("\\", "\\\\") - .replace("\r", "\\r") - .replace("\t", "\\t")); + return escapeDoubleQuotesAndBackslashesAndNewlines(string) + .replace("\r", "\\r").replace("\t", "\\t"); } }; diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java index 7d8a64af50..a0fb6e0636 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java @@ -599,6 +599,9 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { checkTextMessage("struct(name='a\"b').to_proto()", "name: \"a\\\"b\""); checkTextMessage("struct(name='a\\'b').to_proto()", "name: \"a'b\""); checkTextMessage("struct(name='a\\nb').to_proto()", "name: \"a\\nb\""); + + // struct(name="a\\\"b") -> name: "a\\\"b" + checkTextMessage("struct(name='a\\\\\\\"b').to_proto()", "name: \"a\\\\\\\"b\""); } @Test |