From 1b9630f98934bf0332ef4fb7cf22e628876c8bfd Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 13 Feb 2026 10:27:37 -0800 Subject: [PATCH] Small refactoring to make safety clearer --- .../io/opentelemetry/api/common/JsonEncoding.java | 10 ++++++---- .../exporter/internal/otlp/AnyValueMarshaler.java | 2 +- .../internal/otlp/AnyValueStatelessMarshaler.java | 4 ++-- .../internal/otlp/BytesAnyValueMarshaler.java | 9 ++++++--- .../otlp/BytesAnyValueStatelessMarshaler.java | 13 ++++++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/api/all/src/main/java/io/opentelemetry/api/common/JsonEncoding.java b/api/all/src/main/java/io/opentelemetry/api/common/JsonEncoding.java index 49fe90a6e1a..721e8fc5021 100644 --- a/api/all/src/main/java/io/opentelemetry/api/common/JsonEncoding.java +++ b/api/all/src/main/java/io/opentelemetry/api/common/JsonEncoding.java @@ -37,7 +37,7 @@ static void append(StringBuilder sb, Value value) { appendMap(sb, (List) value.getValue()); break; case BYTES: - appendBytes(sb, (ByteBuffer) value.getValue()); + appendBytes(sb, (Value) value); break; case EMPTY: sb.append("null"); @@ -97,9 +97,11 @@ private static void appendDouble(StringBuilder sb, double value) { } } - private static void appendBytes(StringBuilder sb, ByteBuffer value) { - byte[] bytes = new byte[value.remaining()]; - value.get(bytes); + private static void appendBytes(StringBuilder sb, Value value) { + ByteBuffer buf = value.getValue(); + byte[] bytes = new byte[buf.remaining()]; + // getValue() above returns a new ByteBuffer, so mutating its position here is safe + buf.get(bytes); sb.append('"').append(Base64.getEncoder().encodeToString(bytes)).append('"'); } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueMarshaler.java index e2431889d37..16fc7941622 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueMarshaler.java @@ -37,7 +37,7 @@ public static MarshalerWithSize create(Value value) { case KEY_VALUE_LIST: return KeyValueListAnyValueMarshaler.create((List) value.getValue()); case BYTES: - return BytesAnyValueMarshaler.create((ByteBuffer) value.getValue()); + return BytesAnyValueMarshaler.create((Value) value); case EMPTY: return EmptyAnyValueMarshaler.INSTANCE; } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueStatelessMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueStatelessMarshaler.java index 9a441b26bbf..182f12e71c5 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueStatelessMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/AnyValueStatelessMarshaler.java @@ -63,7 +63,7 @@ public void writeTo(Serializer output, Value value, MarshalerContext context) return; case BYTES: BytesAnyValueStatelessMarshaler.INSTANCE.writeTo( - output, (ByteBuffer) value.getValue(), context); + output, (Value) value, context); return; case EMPTY: // no field to write @@ -104,7 +104,7 @@ public int getBinarySerializedSize(Value value, MarshalerContext context) { context); case BYTES: return BytesAnyValueStatelessMarshaler.INSTANCE.getBinarySerializedSize( - (ByteBuffer) value.getValue(), context); + (Value) value, context); case EMPTY: return 0; } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueMarshaler.java index d0a781039be..516159141a1 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueMarshaler.java @@ -5,6 +5,7 @@ package io.opentelemetry.exporter.internal.otlp; +import io.opentelemetry.api.common.Value; import io.opentelemetry.exporter.internal.marshal.CodedOutputStream; import io.opentelemetry.exporter.internal.marshal.MarshalerWithSize; import io.opentelemetry.exporter.internal.marshal.Serializer; @@ -21,9 +22,11 @@ private BytesAnyValueMarshaler(byte[] value) { this.value = value; } - static MarshalerWithSize create(ByteBuffer value) { - byte[] bytes = new byte[value.remaining()]; - value.get(bytes); + static MarshalerWithSize create(Value value) { + ByteBuffer buf = value.getValue(); + byte[] bytes = new byte[buf.remaining()]; + // getValue() above returns a new ByteBuffer, so mutating its position here is safe + buf.get(bytes); return new BytesAnyValueMarshaler(bytes); } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueStatelessMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueStatelessMarshaler.java index 767ff8b8176..c7afff7756b 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueStatelessMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/BytesAnyValueStatelessMarshaler.java @@ -5,6 +5,7 @@ package io.opentelemetry.exporter.internal.otlp; +import io.opentelemetry.api.common.Value; import io.opentelemetry.exporter.internal.marshal.CodedOutputStream; import io.opentelemetry.exporter.internal.marshal.MarshalerContext; import io.opentelemetry.exporter.internal.marshal.Serializer; @@ -14,22 +15,24 @@ import java.nio.ByteBuffer; /** See {@link BytesAnyValueMarshaler}. */ -final class BytesAnyValueStatelessMarshaler implements StatelessMarshaler { +final class BytesAnyValueStatelessMarshaler implements StatelessMarshaler> { static final BytesAnyValueStatelessMarshaler INSTANCE = new BytesAnyValueStatelessMarshaler(); private BytesAnyValueStatelessMarshaler() {} @Override - public void writeTo(Serializer output, ByteBuffer value, MarshalerContext context) + public void writeTo(Serializer output, Value value, MarshalerContext context) throws IOException { byte[] bytes = context.getData(byte[].class); output.writeBytes(AnyValue.BYTES_VALUE, bytes); } @Override - public int getBinarySerializedSize(ByteBuffer value, MarshalerContext context) { - byte[] bytes = new byte[value.remaining()]; - value.get(bytes); + public int getBinarySerializedSize(Value value, MarshalerContext context) { + ByteBuffer buf = value.getValue(); + byte[] bytes = new byte[buf.remaining()]; + // getValue() above returns a new ByteBuffer, so mutating its position here is safe + buf.get(bytes); context.addData(bytes); return AnyValue.BYTES_VALUE.getTagSize() + CodedOutputStream.computeByteArraySizeNoTag(bytes); }