From 2524cdf324e8cb08568848913cadb4466ea7d3dc Mon Sep 17 00:00:00 2001 From: Francesco Guardiani Date: Thu, 26 Nov 2020 12:49:57 +0100 Subject: [PATCH] Fix NPE on null body with structured message (#306) * Fix NPE on null body with structured message Signed-off-by: Francesco Guardiani * Improved test robustness Signed-off-by: Francesco Guardiani --- .../impl/GenericStructuredMessageReader.java | 4 ++-- .../http/vertx/VertxMessageFactory.java | 16 ++++++++++++---- .../http/vertx/VertxMessageFactoryTest.java | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/io/cloudevents/core/message/impl/GenericStructuredMessageReader.java b/core/src/main/java/io/cloudevents/core/message/impl/GenericStructuredMessageReader.java index dee7e559..a78902be 100644 --- a/core/src/main/java/io/cloudevents/core/message/impl/GenericStructuredMessageReader.java +++ b/core/src/main/java/io/cloudevents/core/message/impl/GenericStructuredMessageReader.java @@ -26,8 +26,8 @@ import io.cloudevents.rw.CloudEventRWException; public class GenericStructuredMessageReader extends BaseStructuredMessageReader { - private EventFormat format; - private byte[] payload; + private final EventFormat format; + private final byte[] payload; public GenericStructuredMessageReader(EventFormat format, byte[] payload) { this.format = format; diff --git a/http/vertx/src/main/java/io/cloudevents/http/vertx/VertxMessageFactory.java b/http/vertx/src/main/java/io/cloudevents/http/vertx/VertxMessageFactory.java index 37221283..9231ce5c 100644 --- a/http/vertx/src/main/java/io/cloudevents/http/vertx/VertxMessageFactory.java +++ b/http/vertx/src/main/java/io/cloudevents/http/vertx/VertxMessageFactory.java @@ -6,8 +6,10 @@ import io.cloudevents.core.message.impl.GenericStructuredMessageReader; import io.cloudevents.core.message.impl.MessageUtils; import io.cloudevents.http.vertx.impl.BinaryVertxMessageReaderImpl; import io.cloudevents.http.vertx.impl.CloudEventsHeaders; -import io.cloudevents.http.vertx.impl.VertxWebClientRequestMessageWriterImpl; import io.cloudevents.http.vertx.impl.VertxHttpServerResponseMessageWriterImpl; +import io.cloudevents.http.vertx.impl.VertxWebClientRequestMessageWriterImpl; +import io.cloudevents.lang.Nullable; +import io.cloudevents.rw.CloudEventRWException; import io.cloudevents.rw.CloudEventWriter; import io.vertx.core.*; import io.vertx.core.buffer.Buffer; @@ -35,12 +37,18 @@ public final class VertxMessageFactory { * @param headers Http headers * @param body nullable buffer of the body * @return a Message implementation with potentially an unknown encoding - * @throws IllegalArgumentException If, in case of binary mode, the spec version is invalid */ - public static MessageReader createReader(MultiMap headers, Buffer body) throws IllegalArgumentException { + public static MessageReader createReader(MultiMap headers, @Nullable Buffer body) throws CloudEventRWException { return MessageUtils.parseStructuredOrBinaryMessage( () -> headers.get(HttpHeaders.CONTENT_TYPE), - format -> new GenericStructuredMessageReader(format, body.getBytes()), + format -> { + if (body != null) { + return new GenericStructuredMessageReader(format, body.getBytes()); + } + throw CloudEventRWException.newOther(new IllegalStateException( + "Found a structured message using format " + format.serializedContentType() + " with null body" + )); + }, () -> headers.get(CloudEventsHeaders.SPEC_VERSION), sv -> new BinaryVertxMessageReaderImpl(sv, headers, body) ); diff --git a/http/vertx/src/test/java/io/cloudevents/http/vertx/VertxMessageFactoryTest.java b/http/vertx/src/test/java/io/cloudevents/http/vertx/VertxMessageFactoryTest.java index 039b21d1..ba8a36fd 100644 --- a/http/vertx/src/test/java/io/cloudevents/http/vertx/VertxMessageFactoryTest.java +++ b/http/vertx/src/test/java/io/cloudevents/http/vertx/VertxMessageFactoryTest.java @@ -22,9 +22,11 @@ import io.cloudevents.SpecVersion; import io.cloudevents.core.message.Encoding; import io.cloudevents.core.message.MessageReader; import io.cloudevents.core.mock.CSVFormat; +import io.cloudevents.rw.CloudEventRWException; import io.cloudevents.types.Time; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -33,9 +35,22 @@ import java.util.stream.Stream; import static io.cloudevents.core.test.Data.*; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; public class VertxMessageFactoryTest { + @Test + public void structuredMessageWithoutBody() { + MultiMap headers = MultiMap + .caseInsensitiveMultiMap() + .add("content-type", CSVFormat.INSTANCE.serializedContentType() + "; charset=utf8"); + + assertThatCode(() -> VertxMessageFactory.createReader(headers, null)) + .isInstanceOf(CloudEventRWException.class) + .hasCauseInstanceOf(IllegalStateException.class) + .hasMessageContaining("null body"); + } + @ParameterizedTest @MethodSource("binaryTestArguments") public void readBinary(MultiMap headers, Buffer body, CloudEvent event) {