This is an automated email from the ASF dual-hosted git repository.
pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git
The following commit(s) were added to refs/heads/main by this push:
new 6313843b3a Fix ByteString1C serialization to use SerializationProxy
(#2929)
6313843b3a is described below
commit 6313843b3a8bbd0ff531d8d836e2afc341d874a0
Author: PJ Fanning <[email protected]>
AuthorDate: Tue Apr 28 19:41:04 2026 +0200
Fix ByteString1C serialization to use SerializationProxy (#2929)
* Fix ByteString1C serialization to use SerializationProxy
ByteString1C lacked a writeReplace() method, causing it to be serialized
directly (using @SerialVersionUID(3956956327691936932L)) rather than via
the SerializationProxy used by ByteString1 and ByteStrings. This led to
SerialVersionUID mismatches when deserializing ByteString1C (and all
CompactByteString instances, which are backed by ByteString1C).
Add writeReplace() to ByteString1C so all three concrete ByteString types
consistently route through SerializationProxy on serialization.
Add three new tests:
- Verify ByteString1C serialized bytes do not contain the class name
"ByteString1C" (i.e. the proxy is used, not direct serialization)
- Verify CompactByteString.apply() instances also serialize via proxy
- Verify round-trip serialization for all three concrete types
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko/sessions/a999ad23-eb25-41ef-b082-8e78f5b9353b
Co-authored-by: pjfanning <[email protected]>
* scalafmt
---------
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
---
.../org/apache/pekko/util/ByteStringSpec.scala | 31 ++++++++++++++++++++++
.../scala/org/apache/pekko/util/ByteString.scala | 2 ++
2 files changed, 33 insertions(+)
diff --git
a/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
b/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
index 13e4fd40b5..6c026e45c1 100644
--- a/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
+++ b/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
@@ -2007,6 +2007,37 @@ class ByteStringSpec extends AnyWordSpec with Matchers
with Checkers {
deserialize(serialize(original)) shouldEqual original
}
+
+ "ByteString1C serializes via SerializationProxy not directly" in {
+ val bs1c = ByteString1C(Array[Byte](1, 2, 3))
+ val serialized = serialize(bs1c)
+ // The serialized form must use SerializationProxy, not serialize
ByteString1C directly.
+ // When serialized directly the class descriptor "ByteString1C"
appears in the stream;
+ // with writeReplace the proxy class name appears instead.
+ val streamContent = new String(serialized, StandardCharsets.ISO_8859_1)
+ (streamContent should not).include("ByteString1C")
+ deserialize(serialized) shouldEqual bs1c
+ }
+
+ "CompactByteString instances serialize via SerializationProxy" in {
+ val viaApply = CompactByteString(Array[Byte](10, 20, 30))
+ val viaString = CompactByteString("hello")
+ val serializedApply = serialize(viaApply)
+ val serializedString = serialize(viaString)
+ (new String(serializedApply, StandardCharsets.ISO_8859_1) should
not).include("ByteString1C")
+ (new String(serializedString, StandardCharsets.ISO_8859_1) should
not).include("ByteString1C")
+ deserialize(serializedApply) shouldEqual viaApply
+ deserialize(serializedString) shouldEqual viaString
+ }
+
+ "each ByteString concrete type round-trips via serialization" in {
+ val bs1c = ByteString1C(Array[Byte](1, 2, 3))
+ val bs1 = bs1c.toByteString1
+ val bss = bs1 ++ ByteString1C(Array[Byte](4, 5, 6))
+ deserialize(serialize(bs1c)) shouldEqual bs1c
+ deserialize(serialize(bs1)) shouldEqual bs1
+ deserialize(serialize(bss)) shouldEqual bss
+ }
}
"unsafely wrap and unwrap bytes" in {
diff --git a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
index 0526d2855d..ab9b8f4a5f 100644
--- a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
@@ -410,6 +410,8 @@ object ByteString {
private[pekko] override def writeToOutputStream(os: ObjectOutputStream):
Unit =
toByteString1.writeToOutputStream(os)
+ protected def writeReplace(): AnyRef = new SerializationProxy(this)
+
override def copyToBuffer(buffer: ByteBuffer): Int =
writeToBuffer(buffer, offset = 0)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]