JAMES-2541 Structural runtime checks of blob parts upon Store<T>::read
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/639aabca Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/639aabca Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/639aabca Branch: refs/heads/master Commit: 639aabca86f8ea52ed78bdc1cfb1b009f409891e Parents: b445867 Author: Benoit Tellier <[email protected]> Authored: Thu Sep 6 17:54:49 2018 +0700 Committer: Benoit Tellier <[email protected]> Committed: Mon Sep 10 17:17:41 2018 +0700 ---------------------------------------------------------------------- .../java/org/apache/james/blob/api/Store.java | 5 ++++ .../james/blob/mail/MimeMessageStore.java | 8 +++++++ .../james/blob/mail/MimeMessageStoreTest.java | 24 ++++++++++++++++++++ 3 files changed, 37 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/639aabca/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java ---------------------------------------------------------------------- diff --git a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java index 47c4988..87588a8 100644 --- a/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java +++ b/server/blob/blob-api/src/main/java/org/apache/james/blob/api/Store.java @@ -20,6 +20,7 @@ package org.apache.james.blob.api; import java.io.InputStream; +import java.util.Collection; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -62,6 +63,8 @@ public interface Store<T> { } interface Decoder<T> { + void validateInput(Collection<BlobType> input); + T decode(Map<BlobType, byte[]> streams); } @@ -98,6 +101,8 @@ public interface Store<T> { @Override public CompletableFuture<T> read(Map<BlobType, BlobId> blobIds) { + decoder.validateInput(blobIds.keySet()); + CompletableFuture<ImmutableMap<BlobType, byte[]>> binaries = FluentFutureStream.of(blobIds.entrySet() .stream() .map(entry -> blobStore.readBytes(entry.getValue()) http://git-wip-us.apache.org/repos/asf/james-project/blob/639aabca/server/blob/mail-store/src/main/java/org/apache/james/blob/mail/MimeMessageStore.java ---------------------------------------------------------------------- diff --git a/server/blob/mail-store/src/main/java/org/apache/james/blob/mail/MimeMessageStore.java b/server/blob/mail-store/src/main/java/org/apache/james/blob/mail/MimeMessageStore.java index 5c2e444..ef718fc 100644 --- a/server/blob/mail-store/src/main/java/org/apache/james/blob/mail/MimeMessageStore.java +++ b/server/blob/mail-store/src/main/java/org/apache/james/blob/mail/MimeMessageStore.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.nio.ByteBuffer; +import java.util.Collection; import java.util.Map; import java.util.Properties; @@ -106,6 +107,13 @@ public class MimeMessageStore extends Store.Impl<MimeMessage> { static class MailDecoder implements Decoder<MimeMessage> { @Override + public void validateInput(Collection<BlobType> input) { + Preconditions.checkArgument(input.contains(HEADER_BLOB_TYPE), "Expecting 'mailHeader' blobId to be specified"); + Preconditions.checkArgument(input.contains(BODY_BLOB_TYPE), "Expecting 'mailBody' blobId to be specified"); + Preconditions.checkArgument(input.size() == 2, "blobId other than 'mailHeader' or 'mailBody' are not supported"); + } + + @Override public MimeMessage decode(Map<BlobType, byte[]> streams) { Preconditions.checkNotNull(streams); Preconditions.checkArgument(streams.containsKey(HEADER_BLOB_TYPE)); http://git-wip-us.apache.org/repos/asf/james-project/blob/639aabca/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java ---------------------------------------------------------------------- diff --git a/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java b/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java index 5a896ea..4db2110 100644 --- a/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java +++ b/server/blob/mail-store/src/test/java/org/apache/james/blob/mail/MimeMessageStoreTest.java @@ -36,6 +36,7 @@ import org.apache.james.util.MimeMessageUtil; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.testcontainers.shaded.com.google.common.collect.ImmutableMap; class MimeMessageStoreTest { private static final HashBlobId.Factory BLOB_ID_FACTORY = new HashBlobId.Factory(); @@ -62,6 +63,29 @@ class MimeMessageStoreTest { } @Test + void readShouldThrowWhenMissingHeaderBlobs() { + assertThatThrownBy(() -> testee.read(ImmutableMap.of( + MimeMessageStore.HEADER_BLOB_TYPE, BLOB_ID_FACTORY.randomId()))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void readShouldThrowWhenMissingBodyBlobs() { + assertThatThrownBy(() -> testee.read(ImmutableMap.of( + MimeMessageStore.BODY_BLOB_TYPE, BLOB_ID_FACTORY.randomId()))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void readShouldThrowWhenExtraBodyBlobs() { + assertThatThrownBy(() -> testee.read(ImmutableMap.of( + MimeMessageStore.BODY_BLOB_TYPE, BLOB_ID_FACTORY.randomId(), + MimeMessageStore.HEADER_BLOB_TYPE, BLOB_ID_FACTORY.randomId(), + new Store.BlobType("Unknown"), BLOB_ID_FACTORY.randomId()))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test void mailStoreShouldPreserveContent() throws Exception { MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() .addFrom("[email protected]") --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
