apoc.export.util.LimitedSizeInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc-common Show documentation
Show all versions of apoc-common Show documentation
Data types package for Neo4j Procedures
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package apoc.export.util;
import static apoc.ApocConfig.APOC_MAX_DECOMPRESSION_RATIO;
import static apoc.ApocConfig.DEFAULT_MAX_DECOMPRESSION_RATIO;
import static apoc.ApocConfig.apocConfig;
import java.io.IOException;
import java.io.InputStream;
public class LimitedSizeInputStream extends InputStream {
public static final String SIZE_EXCEEDED_ERROR =
"""
The file dimension exceeded maximum size in bytes, %s,
which is %s times the width of the original file.
The InputStream has been blocked because the file could be a compression bomb attack.""";
public static final int SIZE_MULTIPLIER =
apocConfig().getInt(APOC_MAX_DECOMPRESSION_RATIO, DEFAULT_MAX_DECOMPRESSION_RATIO);
private final InputStream stream;
private final long maxSize;
private long total;
public LimitedSizeInputStream(InputStream stream, long maxSize) {
this.stream = stream;
this.maxSize = maxSize;
}
@Override
public int read() throws IOException {
int i = stream.read();
if (i >= 0) incrementCounter(1);
return i;
}
@Override
public int read(byte b[], int off, int len) throws IOException {
int i = stream.read(b, off, len);
if (i >= 0) incrementCounter(i);
return i;
}
private void incrementCounter(int size) throws IOException {
// in some test cases, e.g. UtilIT.redirectShouldWorkWhenProtocolNotChangesWithUrlLocation,
// the StreamConnection.getLength() returns `-1` because of content length not known,
// therefore we skip these cases
if (maxSize < 0) {
return;
}
total += size;
if (total > maxSize) {
close();
String msgError = String.format(SIZE_EXCEEDED_ERROR, maxSize, SIZE_MULTIPLIER);
throw new IOException(msgError);
}
}
public static InputStream toLimitedIStream(InputStream stream, long total) {
// to prevent potential bomb attack
return new LimitedSizeInputStream(stream, total * SIZE_MULTIPLIER);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy