Skip to content

Commit 7d3b4f2

Browse files
adwsinghrhernandez35
authored andcommitted
Add stricter verifications while reading lists in Json Codec
1 parent f7be31c commit 7d3b4f2

2 files changed

Lines changed: 90 additions & 1 deletion

File tree

codecs/json-codec/src/main/java/software/amazon/smithy/java/json/jackson/JacksonJsonDeserializer.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package software.amazon.smithy.java.json.jackson;
77

88
import static com.fasterxml.jackson.core.JsonToken.END_ARRAY;
9+
import static com.fasterxml.jackson.core.JsonToken.END_OBJECT;
910
import static com.fasterxml.jackson.core.JsonToken.VALUE_NULL;
1011

1112
import com.fasterxml.jackson.core.Base64Variants;
@@ -274,9 +275,19 @@ public <T> void readStruct(Schema schema, T state, StructMemberConsumer<T> struc
274275
@Override
275276
public <T> void readList(Schema schema, T state, ListMemberConsumer<T> listMemberConsumer) {
276277
try {
277-
for (var token = parser.nextToken(); token != END_ARRAY; token = parser.nextToken()) {
278+
if (!parser.isExpectedStartArrayToken()) {
279+
throw new SerializationException("Expected a list, but found " + describeToken());
280+
}
281+
boolean notEoa;
282+
for (
283+
var token = parser.nextToken();
284+
(notEoa = (token != END_ARRAY)) && token != END_OBJECT && token != null;
285+
token = parser.nextToken()) {
278286
listMemberConsumer.accept(state, this);
279287
}
288+
if (notEoa) {
289+
throw new SerializationException("Expected end of list, but found " + describeToken());
290+
}
280291
} catch (Exception e) {
281292
throw new SerializationException(e);
282293
}

codecs/json-codec/src/test/java/software/amazon/smithy/java/json/JsonDeserializerTest.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,84 @@ public void deserializesList() {
223223
}
224224
}
225225

226+
@Test
227+
public void deserializesEmptyList() {
228+
try (var codec = JsonCodec.builder().build()) {
229+
var de = codec.createDeserializer("[]".getBytes(StandardCharsets.UTF_8));
230+
List<String> values = new ArrayList<>();
231+
232+
de.readList(PreludeSchemas.DOCUMENT, null, (ignore, listDe) -> {
233+
values.add(listDe.readString(PreludeSchemas.STRING));
234+
});
235+
236+
assertThat(values, hasSize(0));
237+
}
238+
}
239+
240+
@Test
241+
public void throwsWhenReadListGetsObject() {
242+
try (var codec = JsonCodec.builder().build()) {
243+
var de = codec.createDeserializer("{\"foo\":\"bar\"}".getBytes(StandardCharsets.UTF_8));
244+
List<String> values = new ArrayList<>();
245+
246+
var e = Assertions.assertThrows(SerializationException.class, () -> {
247+
de.readList(PreludeSchemas.DOCUMENT, values, (list, listDe) -> {
248+
list.add(listDe.readString(PreludeSchemas.STRING));
249+
});
250+
});
251+
252+
assertThat(e.getMessage(), equalTo("Expected a list, but found Object value"));
253+
}
254+
}
255+
256+
@Test
257+
public void throwsWhenReadListGetsString() {
258+
try (var codec = JsonCodec.builder().build()) {
259+
var de = codec.createDeserializer("\"not a list\"".getBytes(StandardCharsets.UTF_8));
260+
List<String> values = new ArrayList<>();
261+
262+
var e = Assertions.assertThrows(SerializationException.class, () -> {
263+
de.readList(PreludeSchemas.DOCUMENT, values, (list, listDe) -> {
264+
list.add(listDe.readString(PreludeSchemas.STRING));
265+
});
266+
});
267+
268+
assertThat(e.getMessage(), equalTo("Expected a list, but found String value"));
269+
}
270+
}
271+
272+
@Test
273+
public void throwsWhenReadListGetsEmptyObject() {
274+
try (var codec = JsonCodec.builder().build()) {
275+
var de = codec.createDeserializer("{}".getBytes(StandardCharsets.UTF_8));
276+
List<String> values = new ArrayList<>();
277+
278+
var e = Assertions.assertThrows(SerializationException.class, () -> {
279+
de.readList(PreludeSchemas.DOCUMENT, values, (list, listDe) -> {
280+
list.add(listDe.readString(PreludeSchemas.STRING));
281+
});
282+
});
283+
284+
assertThat(e.getMessage(), equalTo("Expected a list, but found Object value"));
285+
}
286+
}
287+
288+
@Test
289+
public void throwsOnUnfinishedList() {
290+
try (var codec = JsonCodec.builder().build()) {
291+
var de = codec.createDeserializer("[{}".getBytes(StandardCharsets.UTF_8));
292+
List<String> values = new ArrayList<>();
293+
294+
var e = Assertions.assertThrows(SerializationException.class, () -> {
295+
de.readList(PreludeSchemas.DOCUMENT, values, (list, listDe) -> {
296+
list.add(listDe.readString(PreludeSchemas.STRING));
297+
});
298+
});
299+
300+
assertThat(e.getMessage(), equalTo("Expected end of list, but found Object value"));
301+
}
302+
}
303+
226304
@Test
227305
public void deserializesMap() {
228306
try (var codec = JsonCodec.builder().build()) {

0 commit comments

Comments
 (0)