You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2026/07/12 19:47:47 UTC
(cxf) branch 4.1.x-fixes updated (f2ac92f01e5 -> b9be4344dec)
This is an automated email from the ASF dual-hosted git repository.
reta pushed a change to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
from f2ac92f01e5 Recording .gitmergeinfo Changes
new a5c617630eb Add maxSize to BinaryDataProvider so the payload size could be constrained (to 1Gb by default) (#3301)
new b9be4344dec Recording .gitmergeinfo Changes
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.gitmergeinfo | 2 ++
.../java/org/apache/cxf/helpers/CastUtils.java | 10 +++++++-
.../main/java/org/apache/cxf/helpers/IOUtils.java | 30 ++++++++++++++++++----
.../java/org/apache/cxf/io/CachedOutputStream.java | 8 +++++-
.../cxf/jaxrs/provider/BinaryDataProvider.java | 7 ++++-
.../cxf/jaxrs/provider/BinaryDataProviderTest.java | 19 ++++++++++++++
.../cache/CacheControlClientReaderInterceptor.java | 9 +++++--
.../jaxrs/client/cache/CacheControlFeature.java | 8 +++++-
8 files changed, 82 insertions(+), 11 deletions(-)
(cxf) 02/02: Recording .gitmergeinfo Changes
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
commit b9be4344dec6c4a5e350c8d54e1175cb37c54309
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sun Jul 12 15:44:38 2026 -0400
Recording .gitmergeinfo Changes
---
.gitmergeinfo | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.gitmergeinfo b/.gitmergeinfo
index 10fe2629b65..d9a12f4f483 100644
--- a/.gitmergeinfo
+++ b/.gitmergeinfo
@@ -54,6 +54,7 @@ M 14af98e9ae2193603f8fcf82dde271af065cabb4
M 15ef60633f09b27a131202c303de95f0f88327c2
M 166f4b3c04c12445b1d17b7d10cedaa2ae3b12c0
M 16881b7b614f4fede59dd801ec70e04d00668870
+M 16ac0e403ca3cc5f97d3c93d8ccfe98d993b4a66
M 16e15c9a45a8d7325b8a3f4259c8f5eab289e9ee
M 174d899264cd8216fe8258139ed35cf300c931a3
M 17d67e790c59c9f8afc364267657b39ad1e915b3
@@ -211,6 +212,7 @@ M 767e7614c2ee24542dcb51ba5a374b8232327f52
M 771f1712d9ca7b2c71781c6241a521f017619ab2
M 783a56bf623759c965079a8b93b3dd5ee56e96b9
M 7844187c246d55ad3e00a4caeeefb3c1ea7593b5
+M 7a12ad6adb903edb0e1952ba366e6a6da7d89474
M 7a19b0a9c001c7cd47611aa9143588b88ec08eaf
M 7a40959a0cda9e3e40d053cfe57915dfa714f0dd
M 7aa721f9a36491ff27d6a323d8586d8c1b20240d
(cxf) 01/02: Add maxSize to BinaryDataProvider so the payload size could be constrained (to 1Gb by default) (#3301)
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
commit a5c617630eb5b81f0f2f6cf6f3580ebb902a4cbc
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Jul 11 11:58:23 2026 -0400
Add maxSize to BinaryDataProvider so the payload size could be constrained (to 1Gb by default) (#3301)
(cherry picked from commit da5edccdb85138bad83858f05eba10dfe5df4212)
---
.../java/org/apache/cxf/helpers/CastUtils.java | 10 +++++++-
.../main/java/org/apache/cxf/helpers/IOUtils.java | 30 ++++++++++++++++++----
.../java/org/apache/cxf/io/CachedOutputStream.java | 8 +++++-
.../cxf/jaxrs/provider/BinaryDataProvider.java | 7 ++++-
.../cxf/jaxrs/provider/BinaryDataProviderTest.java | 19 ++++++++++++++
.../cache/CacheControlClientReaderInterceptor.java | 9 +++++--
.../jaxrs/client/cache/CacheControlFeature.java | 8 +++++-
7 files changed, 80 insertions(+), 11 deletions(-)
diff --git a/core/src/main/java/org/apache/cxf/helpers/CastUtils.java b/core/src/main/java/org/apache/cxf/helpers/CastUtils.java
index 958ef5f5e44..74c3db05da9 100644
--- a/core/src/main/java/org/apache/cxf/helpers/CastUtils.java
+++ b/core/src/main/java/org/apache/cxf/helpers/CastUtils.java
@@ -92,5 +92,13 @@ public final class CastUtils {
return (Map.Entry<T, U>)p;
}
-
+ public static int cast(long value) {
+ if (value > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ } else if (value < Integer.MIN_VALUE) {
+ return Integer.MIN_VALUE;
+ } else {
+ return (int) value;
+ }
+ }
}
diff --git a/core/src/main/java/org/apache/cxf/helpers/IOUtils.java b/core/src/main/java/org/apache/cxf/helpers/IOUtils.java
index be05fe9981b..37507334e2d 100644
--- a/core/src/main/java/org/apache/cxf/helpers/IOUtils.java
+++ b/core/src/main/java/org/apache/cxf/helpers/IOUtils.java
@@ -34,10 +34,14 @@ import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Objects;
+import org.apache.cxf.common.util.SystemPropertyAction;
import org.apache.cxf.io.CopyingOutputStream;
import org.apache.cxf.io.Transferable;
public final class IOUtils {
+ public static final int DEFAULT_BINARY_MAX_SIZE =
+ SystemPropertyAction.getInteger("org.apache.cxf.binary-max-size", 1073741824 /* 1Gb */);
+
public static final Charset UTF8_CHARSET = java.nio.charset.StandardCharsets.UTF_8;
public static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
@@ -176,7 +180,7 @@ public final class IOUtils {
if (output instanceof CopyingOutputStream) {
return ((CopyingOutputStream)output).copyFrom(input);
}
- return copy(input, output, DEFAULT_BUFFER_SIZE);
+ return copy(input, output, DEFAULT_BUFFER_SIZE, -1);
}
public static int copyAndCloseInput(final InputStream input,
@@ -189,7 +193,7 @@ public final class IOUtils {
public static int copyAndCloseInput(final InputStream input,
final OutputStream output, int bufferSize) throws IOException {
try (InputStream in = input) {
- return copy(in, output, bufferSize);
+ return copy(in, output, bufferSize, -1);
}
}
@@ -206,9 +210,13 @@ public final class IOUtils {
copy(r, output, bufferSize);
}
}
+
+ public static int copy(final InputStream input, final OutputStream output, int bufferSize) throws IOException {
+ return copy(input, output, bufferSize, -1);
+ }
public static int copy(final InputStream input, final OutputStream output,
- int bufferSize) throws IOException {
+ int bufferSize, int maxSize) throws IOException {
Objects.requireNonNull(input, "The inputStream is required but null value was provided");
Objects.requireNonNull(output, "The outputStream is required but null value was provided");
int avail = input.available();
@@ -228,6 +236,10 @@ public final class IOUtils {
output.write(buffer, 0, n);
total += n;
n = input.read(buffer);
+
+ if (maxSize > 0 /* -1 sets to unlimited */ && total > maxSize) {
+ throw new IOException("The total limit of " + maxSize + " bytes exceeded, data is too large");
+ }
}
return total;
}
@@ -426,15 +438,23 @@ public final class IOUtils {
n = input.read(buffer, 0, n);
}
}
-
+
+ /**
+ * @deprecated use {@link #readBytesFromStream(InputStream, int)}
+ */
+ @Deprecated(forRemoval = true)
public static byte[] readBytesFromStream(InputStream in) throws IOException {
+ return readBytesFromStream(in, -1);
+ }
+
+ public static byte[] readBytesFromStream(InputStream in, int maxSize) throws IOException {
Objects.requireNonNull(in, "The inputStream is required but null value was provided");
int i = in.available();
if (i < DEFAULT_BUFFER_SIZE) {
i = DEFAULT_BUFFER_SIZE;
}
try (InputStream input = in; ByteArrayOutputStream bos = new ByteArrayOutputStream(i)) {
- copy(input, bos);
+ copy(input, bos, DEFAULT_BUFFER_SIZE, maxSize);
return bos.toByteArray();
}
}
diff --git a/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java b/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java
index c19e7cfbe8b..200b0dfe248 100644
--- a/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java
+++ b/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java
@@ -44,6 +44,7 @@ import javax.crypto.CipherOutputStream;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.common.util.SystemPropertyAction;
+import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.helpers.FileUtils;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
@@ -334,9 +335,14 @@ public class CachedOutputStream extends OutputStream {
}
throw new IOException("Unknown format of currentStream");
}
+
+ if (totalLength > Integer.MAX_VALUE) {
+ throw new IOException("The total limit of " + Integer.MAX_VALUE + " bytes exceeded, data is too large");
+ }
+
// read the file
try (InputStream fin = createInputStream(tempFile)) {
- return IOUtils.readBytesFromStream(fin);
+ return IOUtils.readBytesFromStream(fin, CastUtils.cast(maxSize));
}
}
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/BinaryDataProvider.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/BinaryDataProvider.java
index d9604618d10..4d521f806b7 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/BinaryDataProvider.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/BinaryDataProvider.java
@@ -71,6 +71,7 @@ public class BinaryDataProvider<T> extends AbstractConfigurableProvider
private static final Logger LOG = LogUtils.getL7dLogger(BinaryDataProvider.class);
private int bufferSize = IOUtils.DEFAULT_BUFFER_SIZE;
+ private int maxSize = IOUtils.DEFAULT_BINARY_MAX_SIZE;
private boolean reportByteArraySize;
private boolean closeResponseInputStream = true;
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mt) {
@@ -105,7 +106,7 @@ public class BinaryDataProvider<T> extends AbstractConfigurableProvider
return clazz.cast(new InputStreamReader(is, getEncoding(type)));
}
if (byte[].class.isAssignableFrom(clazz)) {
- return clazz.cast(IOUtils.readBytesFromStream(is));
+ return clazz.cast(IOUtils.readBytesFromStream(is, maxSize));
}
if (File.class.isAssignableFrom(clazz)) {
LOG.warning("Reading data into File objects with the help of pre-packaged"
@@ -259,6 +260,10 @@ public class BinaryDataProvider<T> extends AbstractConfigurableProvider
this.bufferSize = bufferSize;
}
+ public void setMaxSize(int maxSize) {
+ this.maxSize = maxSize;
+ }
+
protected NioWriteHandler getNioHandler(final InputStream in) {
return new NioWriteHandler() {
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/BinaryDataProviderTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/BinaryDataProviderTest.java
index 02d648c0971..b3c8395d3a5 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/BinaryDataProviderTest.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/BinaryDataProviderTest.java
@@ -39,8 +39,11 @@ import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.junit.Test;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class BinaryDataProviderTest {
@@ -133,6 +136,22 @@ public class BinaryDataProviderTest {
assertArrayEquals(os.toByteArray(), new String("hi").getBytes());
}
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testReadBytesMaxSize() throws Exception {
+ final int maxSize = 4096;
+ final BinaryDataProvider p = new BinaryDataProvider();
+ p.setMaxSize(maxSize);
+
+ final byte[] bytes = new byte[maxSize + 1]; /* maxSize + 1 byte */
+ final IOException ex = assertThrows(IOException.class,
+ () -> p.readFrom(byte[].class, byte[].class, new Annotation[]{},
+ MediaType.APPLICATION_OCTET_STREAM_TYPE,
+ new MetadataMap<String, Object>(),
+ new ByteArrayInputStream(bytes)));
+
+ assertThat(ex.getMessage(), equalTo("The total limit of 4096 bytes exceeded, data is too large"));
+ }
private static final class StreamingOutputImpl implements StreamingOutput {
diff --git a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlClientReaderInterceptor.java b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlClientReaderInterceptor.java
index c3f303921d2..04729bce260 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlClientReaderInterceptor.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlClientReaderInterceptor.java
@@ -49,6 +49,7 @@ public class CacheControlClientReaderInterceptor implements ReaderInterceptor {
@Context
private UriInfo uriInfo;
private boolean cacheResponseInputStream;
+ private int maxSize = IOUtils.DEFAULT_BINARY_MAX_SIZE;
public CacheControlClientReaderInterceptor(final Cache<Key, Entry> cache) {
this.cache = cache;
@@ -63,6 +64,10 @@ public class CacheControlClientReaderInterceptor implements ReaderInterceptor {
return this;
}
+ public void setMaxSize(int maxSize) {
+ this.maxSize = maxSize;
+ }
+
@Override
public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
Object cachedEntity = context.getProperty(CacheControlClientRequestFilter.CACHED_ENTITY_PROPERTY);
@@ -97,7 +102,7 @@ public class CacheControlClientReaderInterceptor implements ReaderInterceptor {
final boolean validCacheControl = isCacheControlValid(context, cacheControl);
if (validCacheControl && cacheResponseInputStream) {
// if Cache-Control is set and the stream needs to be cached then do it
- cachedBytes = IOUtils.readBytesFromStream(context.getInputStream());
+ cachedBytes = IOUtils.readBytesFromStream(context.getInputStream(), maxSize);
context.setInputStream(new ByteArrayInputStream(cachedBytes));
}
// Read the stream and get the actual entity
@@ -117,7 +122,7 @@ public class CacheControlClientReaderInterceptor implements ReaderInterceptor {
} else if (responseEntity instanceof InputStream) {
// read the stream, cache it, the cached bytes will be returned immediately
// when a client cache will return them
- byte[] bytes = IOUtils.readBytesFromStream((InputStream)responseEntity);
+ byte[] bytes = IOUtils.readBytesFromStream((InputStream)responseEntity, maxSize);
ser = new BytesEntity(bytes, true);
responseEntity = new ByteArrayInputStream(bytes);
}
diff --git a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlFeature.java b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlFeature.java
index 37bbc3ac573..bdb8cab1a8a 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlFeature.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/cache/CacheControlFeature.java
@@ -39,7 +39,7 @@ import jakarta.annotation.PreDestroy;
import jakarta.ws.rs.core.Feature;
import jakarta.ws.rs.core.FeatureContext;
import jakarta.ws.rs.ext.Provider;
-
+import org.apache.cxf.helpers.IOUtils;
@Provider
public class CacheControlFeature implements Feature, Closeable {
@@ -47,6 +47,7 @@ public class CacheControlFeature implements Feature, Closeable {
private CacheManager manager;
private Cache<Key, Entry> cache;
private boolean cacheResponseInputStream;
+ private int maxSize = IOUtils.DEFAULT_BINARY_MAX_SIZE;
@Override
public boolean configure(final FeatureContext context) {
@@ -55,10 +56,15 @@ public class CacheControlFeature implements Feature, Closeable {
context.register(new CacheControlClientRequestFilter(entryCache));
CacheControlClientReaderInterceptor reader = new CacheControlClientReaderInterceptor(entryCache);
reader.setCacheResponseInputStream(cacheResponseInputStream);
+ reader.setMaxSize(maxSize);
context.register(reader);
return true;
}
+ public void setMaxSize(int maxSize) {
+ this.maxSize = maxSize;
+ }
+
@PreDestroy // TODO: check it is called
public void close() {
for (final Closeable c : Arrays.asList(cache, manager, provider)) {