Skip to content

Commit 14f8a0a

Browse files
committed
Fix #122
1 parent cec3f52 commit 14f8a0a

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

csv/src/main/java/com/fasterxml/jackson/dataformat/csv/CsvParser.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
public class CsvParser
2525
extends ParserMinimalBase
2626
{
27-
/**
27+
// @since 2.9.9: just to protect against bugs, DoS, limit number of column defs we may read
28+
private final static int MAX_COLUMNS = 99999;
29+
30+
/**
2831
* Enumeration that defines all togglable features for CSV parsers
2932
*/
3033
public enum Feature
@@ -351,7 +354,10 @@ private Feature(boolean defaultState) {
351354
public CsvParser(CsvIOContext ctxt, int stdFeatures, int csvFeatures,
352355
ObjectCodec codec, Reader reader)
353356
{
354-
super(stdFeatures);
357+
super(stdFeatures);
358+
if (reader == null) {
359+
throw new IllegalArgumentException("Can not pass `null` as `java.io.Reader` to read from");
360+
}
355361
_objectCodec = codec;
356362
_textBuffer = ctxt.csvTextBuffer();
357363
DupDetector dups = JsonParser.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(stdFeatures)
@@ -720,17 +726,22 @@ protected void _readHeaderLine() throws IOException {
720726
if ((name = _reader.nextString()) != null) {
721727
_reportError(String.format("Extra header %s", name));
722728
}
723-
}
724-
else {
725-
//noinspection StatementWithEmptyBody
726-
while (_reader.nextString() != null) { /* does nothing */ }
729+
} else {
730+
int allowed = MAX_COLUMNS;
731+
while (_reader.nextString() != null) {
732+
// If we don't care about validation, just skip. But protect against infinite loop
733+
if (--allowed < 0) {
734+
_reportError("Internal error: skipped "+MAX_COLUMNS+" header columns");
735+
}
736+
}
727737
}
728738
return;
729739
}
730740

731741
// either the schema is empty or reorder columns flag is set
732742
String name;
733743
CsvSchema.Builder builder = _schema.rebuild().clearColumns();
744+
int count = 0;
734745

735746
while ((name = _reader.nextString()) != null) {
736747
// one more thing: always trim names, regardless of config settings
@@ -743,6 +754,9 @@ protected void _readHeaderLine() throws IOException {
743754
} else {
744755
builder.addColumn(name);
745756
}
757+
if (++count > MAX_COLUMNS) {
758+
_reportError("Internal error: reached maximum of "+MAX_COLUMNS+" header columns");
759+
}
746760
}
747761

748762
// Ok: did we get any columns?
@@ -777,9 +791,8 @@ protected JsonToken _handleStartDoc() throws IOException
777791
_reader.skipLeadingComments();
778792
}
779793

780-
/* Only one real complication, actually; empy documents (zero bytes).
781-
* Those have no entries. Should be easy enough to detect like so:
782-
*/
794+
// Only one real complication, actually; empty documents (zero bytes).
795+
// Those have no entries. Should be easy enough to detect like so:
783796
final boolean wrapAsArray = Feature.WRAP_AS_ARRAY.enabledIn(_formatFeatures);
784797
if (!_reader.hasMoreInput()) {
785798
_state = STATE_DOC_END;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.fasterxml.jackson.dataformat.csv;
2+
3+
import java.io.*;
4+
import java.util.Map;
5+
6+
import com.fasterxml.jackson.databind.ObjectReader;
7+
8+
public class NullReader122Test extends ModuleTestBase
9+
{
10+
private final CsvMapper MAPPER = mapperForCsv();
11+
12+
// for [dataformats-text#122]: passing `null` Reader leads to infinite loop
13+
public void testEmptyStream() throws Exception {
14+
CsvSchema columns = CsvSchema.emptySchema().withHeader().withColumnSeparator(';');
15+
ObjectReader r = MAPPER.readerFor(Map.class).with(columns);
16+
try {
17+
/*Object ob =*/ r.readValue((Reader) null);
18+
fail("Should not pass");
19+
} catch (IllegalArgumentException e) {
20+
verifyException(e, "Can not pass `null`");
21+
}
22+
}
23+
}

release-notes/VERSION-2.x

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ Modules:
1010

1111
2.9.9 (not yet released)
1212

13-
#63: `null` Object Id serialized as anchor for YAML
13+
#63: (yaml) `null` Object Id serialized as anchor for YAML
1414
(reported by jflefebvre06@github)
15+
#122: (csv) `readValues(null)` causes infinite loop
16+
(reported by andyeko@github)
1517

1618
2.9.8 (15-Dec-2018)
1719

0 commit comments

Comments
 (0)