From c4618617f60a2830c3e66848592a91d23fb91de8 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 6 Dec 2021 17:11:23 +0100 Subject: [PATCH] Introduce iteration limit to prevent resource exhaustion when reading signatures --- .../pgpainless/signature/SignatureUtils.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java index 3209fc8a..93e8aae0 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java @@ -43,6 +43,8 @@ import org.pgpainless.util.ArmorUtils; */ public final class SignatureUtils { + public static final int MAX_ITERATIONS = 10000; + private SignatureUtils() { } @@ -220,13 +222,28 @@ public final class SignatureUtils { * @throws PGPException in case of an OpenPGP error */ public static List readSignatures(InputStream inputStream) throws IOException, PGPException { + return readSignatures(inputStream, MAX_ITERATIONS); + } + + /** + * Read and return {@link PGPSignature PGPSignatures}. + * This method can deal with signatures that may be armored, compressed and may contain marker packets. + * + * @param inputStream input stream + * @param maxIterations number of loop iterations until reading is aborted + * @return list of encountered signatures + * @throws IOException in case of a stream error + * @throws PGPException in case of an OpenPGP error + */ + public static List readSignatures(InputStream inputStream, int maxIterations) throws IOException, PGPException { List signatures = new ArrayList<>(); InputStream pgpIn = ArmorUtils.getDecoderStream(inputStream); PGPObjectFactory objectFactory = new PGPObjectFactory( pgpIn, ImplementationFactory.getInstance().getKeyFingerprintCalculator()); + int i = 0; Object nextObject; - while ((nextObject = objectFactory.nextObject()) != null) { + while (i++ < maxIterations && (nextObject = objectFactory.nextObject()) != null) { if (nextObject instanceof PGPCompressedData) { PGPCompressedData compressedData = (PGPCompressedData) nextObject; objectFactory = new PGPObjectFactory(compressedData.getDataStream(),