From 5698ccaee6163e70ec40af17c371ee4dc34ebeb7 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Sun, 19 Jul 2015 09:45:56 -0700 Subject: [PATCH] Fix invalid data sharing in Metadata.merge() --- core/src/main/java/io/grpc/Metadata.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/grpc/Metadata.java b/core/src/main/java/io/grpc/Metadata.java index 01999e8e84..1b7d7f4246 100644 --- a/core/src/main/java/io/grpc/Metadata.java +++ b/core/src/main/java/io/grpc/Metadata.java @@ -225,7 +225,11 @@ public abstract class Metadata { "Cannot merge non-serializable metadata into serializable metadata without keys"); } } - store.putAll(other.store); + for (MetadataEntry entry : other.store.values()) { + // Must copy the MetadataEntries since they are mutated. If the two Metadata objects are used + // from different threads it would cause thread-safety issues. + store.put(entry.key.name(), new MetadataEntry(entry)); + } } /** @@ -546,6 +550,16 @@ public abstract class Metadata { this.isBinary = isBinary; } + /** + * Copy constructor. + */ + private MetadataEntry(MetadataEntry entry) { + this.parsed = entry.parsed; + this.key = entry.key; + this.isBinary = entry.isBinary; + this.serializedBinary = entry.serializedBinary; + } + @SuppressWarnings("unchecked") public T getParsed(Key key) { T value = (T) parsed;