Bug#1104933: activemq: diff for NMU version 5.17.6+dfsg-1.1 (3/48)
From
Emmanuel Arias@1:229/2 to
All on Sun Jun 1 01:20:01 2025
[continued from previous message]
++ int size = bytesIn.readInt();
++ if (maxFrameSizeEnabled && size > maxFrameSize) {
++ throw IOExceptionSupport.createFrameSizeException(size, maxFrameSize);
++ }
++ context.setFrameSize(size);
+ }
++ return doUnmarshal(bytesIn);
++ } finally {
++ // After we unmarshal we can clear the context
++ marshallingContext.remove();
+ }
+-
+- Object command = doUnmarshal(bytesIn);
+- // if( !cacheEnabled && ((DataStructure)command).isMarshallAware() ) {
+- // ((MarshallAware) command).setCachedMarshalledForm(this, sequence); +- // }
+- return command;
+ }
+
+ @Override
+@@ -275,19 +281,22 @@
+
+ @Override
+ public Object unmarshal(DataInput dis) throws IOException {
+- DataInput dataIn = dis;
+- if (!sizePrefixDisabled) {
+- int size = dis.readInt();
+- if (maxFrameSizeEnabled && size > maxFrameSize) {
+- throw IOExceptionSupport.createFrameSizeException(size, maxFrameSize);
+- }
+- // int size = dis.readInt();
+- // byte[] data = new byte[size];
+- // dis.readFully(data);
+- // bytesIn.restart(data);
+- // dataIn = bytesIn;
++ try {
++ final var context = new MarshallingContext();
++ marshallingContext.set(context);
++
++ if (!sizePrefixDisabled) {
++ int size = dis.readInt();
++ if (maxFrameSizeEnabled && size > maxFrameSize) {
++ throw IOExceptionSupport.createFrameSizeException(size, maxFrameSize);
++ }
++ context.setFrameSize(size);
++ }
++ return doUnmarshal(dis);
++ } finally {
++ // After we unmarshal we can clear
++ marshallingContext.remove();
+ }
+- return doUnmarshal(dataIn);
+ }
+
+ /**
+@@ -363,7 +372,7 @@
+ this.version = version;
+ }
+
+- public Object doUnmarshal(DataInput dis) throws IOException {
++ private Object doUnmarshal(DataInput dis) throws IOException {
+ byte dataType = dis.readByte();
+ if (dataType != NULL_TYPE) {
+ DataStreamMarshaller dsm = dataMarshallers[dataType & 0xFF];
+@@ -698,4 +707,47 @@
+ }
+ return version2;
+ }
++
++ MarshallingContext getMarshallingContext() {
++ return marshallingContext.get();
++ }
++
++ // Used to track the estimated allocated buffer sizes to validate
++ // against the current frame being processed
++ static class MarshallingContext {
++ // Use primitives to minimize memory footprint
++ private int frameSize = -1;
++ private int estimatedAllocated = 0;
++
++ void setFrameSize(int frameSize) throws IOException {
++ this.frameSize = frameSize;
++ if (frameSize < 0) {
++ throw error("Frame size " + frameSize + " can't be negative.");
++ }
++ }
++
++ void increment(int size) throws IOException {
++ if (size < 0) {
++ throw error("Size " + size + " can't be negative.");
++ }
++ try {
++ estimatedAllocated = Math.addExact(estimatedAllocated, size); ++ } catch (ArithmeticException e) {
++ throw error("Buffer overflow when incrementing size value: " + size);
++ }
++ }
++
++ public int getFrameSize() {
++ return frameSize;
++ }
++
++ public int getEstimatedAllocated() {
++ return estimatedAllocated;
++ }
++
++ private static IOException error(String errorMessage) {
++ return new IOException(new IllegalArgumentException(errorMessage));
++ }
++ }
++
+ }
+--- a/activemq-client/src/main/java/org/apache/activemq/openwire/OpenWireUtil.java
++++ b/activemq-client/src/main/java/org/apache/activemq/openwire/OpenWireUtil.java
+@@ -16,9 +16,56 @@
+ */
+ package org.apache.activemq.openwire;
+
++import java.io.IOException;
++import org.apache.activemq.util.IOExceptionSupport;
++
+ public class OpenWireUtil {
+
+ /**
++ * Verify that the buffer size that will be allocated will not push the total allocated
++ * size of this frame above the expected frame size. This is an estimate as the current
++ * size is only tracked when calls to this method are made and is primarily intended
++ * to prevent large arrays from being created due to an invalid size.
++ *
++ * Also verify the size against configured max frame size.
++ * This check is a sanity check in case of corrupt packets contain invalid size values.
++ *
++ * @param wireFormat configured OpenWireFormat
++ * @param size buffer size to verify
++ * @throws IOException If size is larger than currentFrameSize or maxFrameSize
++ */
++ public static void validateBufferSize(OpenWireFormat wireFormat, int size) throws IOException {
++ validateLessThanFrameSize(wireFormat, size);
++
++ // if currentFrameSize is set and was checked above then this check should not be needed,
++ // but it doesn't hurt to verify again in case the max frame size check was missed
++ // somehow
++ if (wireFormat.isMaxFrameSizeEnabled() && size > wireFormat.getMaxFrameSize()) {
++ throw IOExceptionSupport.createFrameSizeException(size, wireFormat.getMaxFrameSize());
++ }
++ }
++
++ // Verify total tracked sizes will not exceed the overall size of the frame
++ private static void validateLessThanFrameSize(OpenWireFormat wireFormat, int size)
++ throws IOException {
++ final var context = wireFormat.getMarshallingContext();
++ // No information on current frame size so just return
++ if (context == null || context.getFrameSize() < 0) {
++ return;
++ }
++
++ // Increment existing estimated buffer size with new size
++ context.increment(size);
++
++ // We should never be trying to allocate a buffer that is going to push the total
++ // size greater than the entire frame itself
++ if (context.getEstimatedAllocated() > context.getFrameSize()) {
++ throw IOExceptionSupport.createFrameSizeBufferException(
++ context.getEstimatedAllocated(), context.getFrameSize());
++ }
++ }
++
++ /**
+ * Verify that the provided class extends {@link Throwable} and throw an + * {@link IllegalArgumentException} if it does not.
+ *
+--- a/activemq-client/src/main/java/org/apache/activemq/openwire/v1/BaseDataStreamMarshaller.java
++++ b/activemq-client/src/main/java/org/apache/activemq/openwire/v1/BaseDataStreamMarshaller.java
+@@ -411,10 +411,11 @@
+ }
+ }
+
+- protected byte[] tightUnmarshalByteArray(DataInput dataIn, BooleanStream bs) throws IOException {
++ protected byte[] tightUnmarshalByteArray(OpenWireFormat wireFormat, DataInput dataIn, BooleanStream bs) throws IOException {
+ byte rc[] = null;
+ if (bs.readBoolean()) {
+ int size = dataIn.readInt();
++ OpenWireUtil.validateBufferSize(wireFormat, size);
+ rc = new byte[size];
+ dataIn.readFully(rc);
+ }
[continued in next message]
--- SoupGate-Win32 v1.05
* Origin: you cannot sedate... all the things you hate (1:229/2)