From 55927cdfb444abf7d030158d78c14b2786253630 Mon Sep 17 00:00:00 2001 From: zhanghua1831 Date: Tue, 2 Mar 2021 17:15:54 +0800 Subject: [PATCH] fix CVE-2020-28491 --- CVE-2020-28491.patch | 230 ++++++++++++++++++++++++++++++++ jackson-dataformats-binary.spec | 6 +- 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 CVE-2020-28491.patch diff --git a/CVE-2020-28491.patch b/CVE-2020-28491.patch new file mode 100644 index 0000000..b05b9ad --- /dev/null +++ b/CVE-2020-28491.patch @@ -0,0 +1,230 @@ +From de072d314af8f5f269c8abec6930652af67bc8e6 Mon Sep 17 00:00:00 2001 +From: Tatu Saloranta +Date: Fri, 4 Dec 2020 16:27:55 -0800 +Subject: [PATCH] Fix eager allocation aspect of #186 + +--- + .../dataformat/cbor/CBORGenerator.java | 2 +- + .../jackson/dataformat/cbor/CBORParser.java | 115 ++++++++++++++---- + 2 files changed, 90 insertions(+), 27 deletions(-) + +diff --git a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java +index f813f4c..1215c86 100644 +--- a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java ++++ b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java +@@ -190,7 +190,7 @@ public class CBORGenerator extends GeneratorBase + + /** + * Number of elements remaining in the current complex structure (if any), +- * when writing defined-length Arrays, Objects; marker {@link #INDEFINITE_LENGTH} ++ * when writing defined-length Arrays, Objects; marker {code INDEFINITE_LENGTH} + * otherwise. + */ + protected int _currentRemainingElements = INDEFINITE_LENGTH; +diff --git a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java +index 2412c7c..ec89f9b 100644 +--- a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java ++++ b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java +@@ -63,6 +63,10 @@ public final class CBORParser extends ParserMinimalBase + private final static double MATH_POW_2_10 = Math.pow(2, 10); + private final static double MATH_POW_2_NEG14 = Math.pow(2, -14); + ++ // 2.11.4: [dataformats-binary#186] Avoid OOME/DoS for bigger binary; ++ // read only up to 250k ++ protected final static int LONGEST_NON_CHUNKED_BINARY = 250_000; ++ + /* + /********************************************************** + /* Configuration +@@ -1500,13 +1504,15 @@ public final class CBORParser extends ParserMinimalBase + } + } + +- private int _readAndWriteBytes(OutputStream out, int total) throws IOException ++ private int _readAndWriteBytes(OutputStream out, final int total) throws IOException + { + int left = total; + while (left > 0) { + int avail = _inputEnd - _inputPtr; + if (_inputPtr >= _inputEnd) { +- loadMoreGuaranteed(); ++ if (!loadMore()) { ++ _reportIncompleteBinaryRead(total, total-left); ++ } + avail = _inputEnd - _inputPtr; + } + int count = Math.min(avail, left); +@@ -2219,33 +2225,55 @@ public final class CBORParser extends ParserMinimalBase + // either way, got it now + return _inputBuffer[_inputPtr++]; + } +- ++ ++ /** ++ * Helper called to complete reading of binary data ("byte string") in ++ * case contents are needed. ++ */ + @SuppressWarnings("resource") + protected byte[] _finishBytes(int len) throws IOException + { ++ // Chunked? + // First, simple: non-chunked +- if (len >= 0) { ++ if (len <= 0) { + if (len == 0) { + return NO_BYTES; + } +- byte[] b = new byte[len]; +- if (_inputPtr >= _inputEnd) { +- loadMoreGuaranteed(); ++ return _finishChunkedBytes(); ++ } ++ // Non-chunked, contiguous ++ if (len > LONGEST_NON_CHUNKED_BINARY) { ++ // [dataformats-binary#186]: avoid immediate allocation for longest ++ return _finishLongContiguousBytes(len); ++ } ++ ++ final byte[] b = new byte[len]; ++ final int expLen = len; ++ if (_inputPtr >= _inputEnd) { ++ if (!loadMore()) { ++ _reportIncompleteBinaryRead(expLen, 0); + } +- int ptr = 0; +- while (true) { +- int toAdd = Math.min(len, _inputEnd - _inputPtr); +- System.arraycopy(_inputBuffer, _inputPtr, b, ptr, toAdd); +- _inputPtr += toAdd; +- ptr += toAdd; +- len -= toAdd; +- if (len <= 0) { +- return b; +- } +- loadMoreGuaranteed(); ++ } ++ ++ int ptr = 0; ++ while (true) { ++ int toAdd = Math.min(len, _inputEnd - _inputPtr); ++ System.arraycopy(_inputBuffer, _inputPtr, b, ptr, toAdd); ++ _inputPtr += toAdd; ++ ptr += toAdd; ++ len -= toAdd; ++ if (len <= 0) { ++ return b; ++ } ++ if (!loadMore()) { ++ _reportIncompleteBinaryRead(expLen, ptr); + } + } ++ } + ++ // @since 2.12 ++ protected byte[] _finishChunkedBytes() throws IOException ++ { + // or, if not, chunked... + ByteArrayBuilder bb = _getByteArrayBuilder(); + while (true) { +@@ -2262,14 +2290,17 @@ public final class CBORParser extends ParserMinimalBase + throw _constructError("Mismatched chunk in chunked content: expected "+CBORConstants.MAJOR_TYPE_BYTES + +" but encountered "+type); + } +- len = _decodeExplicitLength(ch & 0x1F); ++ int len = _decodeExplicitLength(ch & 0x1F); + if (len < 0) { + throw _constructError("Illegal chunked-length indicator within chunked-length value (type "+CBORConstants.MAJOR_TYPE_BYTES+")"); + } ++ final int chunkLen = len; + while (len > 0) { + int avail = _inputEnd - _inputPtr; + if (_inputPtr >= _inputEnd) { +- loadMoreGuaranteed(); ++ if (!loadMore()) { ++ _reportIncompleteBinaryRead(chunkLen, chunkLen-len); ++ } + avail = _inputEnd - _inputPtr; + } + int count = Math.min(avail, len); +@@ -2280,7 +2311,33 @@ public final class CBORParser extends ParserMinimalBase + } + return bb.toByteArray(); + } +- ++ ++ // @since 2.12 ++ protected byte[] _finishLongContiguousBytes(final int expLen) throws IOException ++ { ++ int left = expLen; ++ ++ // 04-Dec-2020, tatu: Let's NOT use recycled instance since we have much ++ // longer content and there is likely less benefit of trying to recycle ++ // segments ++ try (final ByteArrayBuilder bb = new ByteArrayBuilder(LONGEST_NON_CHUNKED_BINARY >> 1)) { ++ while (left > 0) { ++ int avail = _inputEnd - _inputPtr; ++ if (avail <= 0) { ++ if (!loadMore()) { ++ _reportIncompleteBinaryRead(expLen, expLen-left); ++ } ++ avail = _inputEnd - _inputPtr; ++ } ++ int count = Math.min(avail, left); ++ bb.write(_inputBuffer, _inputPtr, count); ++ _inputPtr += count; ++ left -= count; ++ } ++ return bb.toByteArray(); ++ } ++ } ++ + protected final JsonToken _decodeFieldName() throws IOException + { + if (_inputPtr >= _inputEnd) { +@@ -2429,9 +2486,8 @@ public final class CBORParser extends ParserMinimalBase + } else if (type == CBORConstants.MAJOR_TYPE_INT_NEG) { + name = _numberToName(ch, true); + } else if (type == CBORConstants.MAJOR_TYPE_BYTES) { +- /* 08-Sep-2014, tatu: As per [Issue#5], there are codecs +- * (f.ex. Perl module "CBOR::XS") that use Binary data... +- */ ++ // 08-Sep-2014, tatu: As per [Issue#5], there are codecs ++ // (f.ex. Perl module "CBOR::XS") that use Binary data... + final int blen = _decodeExplicitLength(ch & 0x1F); + byte[] b = _finishBytes(blen); + // TODO: Optimize, if this becomes commonly used & bottleneck; we have +@@ -2984,7 +3040,7 @@ public final class CBORParser extends ParserMinimalBase + /********************************************************** + */ + +- protected final boolean loadMore() throws IOException ++ protected boolean loadMore() throws IOException + { + if (_inputStream != null) { + _currInputProcessed += _inputEnd; +@@ -3005,7 +3061,7 @@ public final class CBORParser extends ParserMinimalBase + return false; + } + +- protected final void loadMoreGuaranteed() throws IOException { ++ protected void loadMoreGuaranteed() throws IOException { + if (!loadMore()) { _reportInvalidEOF(); } + } + +@@ -3129,6 +3185,13 @@ public final class CBORParser extends ParserMinimalBase + _reportInvalidOther(mask); + } + ++ // @since 2.12 ++ protected void _reportIncompleteBinaryRead(int expLen, int actLen) throws IOException ++ { ++ _reportInvalidEOF(String.format(" for Binary value: expected %d bytes, only found %d", ++ expLen, actLen), _currToken); ++ } ++ + /* + /********************************************************** + /* Internal methods, other +-- +2.23.0 + diff --git a/jackson-dataformats-binary.spec b/jackson-dataformats-binary.spec index e241d07..a3707e6 100644 --- a/jackson-dataformats-binary.spec +++ b/jackson-dataformats-binary.spec @@ -1,10 +1,11 @@ Name: jackson-dataformats-binary Version: 2.9.4 -Release: 5 +Release: 6 Summary: A multi-module umbrella project for Jackson standard binary data format backends License: ASL 2.0 and BSD URL: https://github.com/FasterXML/jackson-dataformats-binary Source0: https://github.com/FasterXML/jackson-dataformats-binary/archive/%{name}-%{version}.tar.gz +Patch0000: CVE-2020-28491.patch BuildArch: noarch BuildRequires: maven-local, mvn(com.fasterxml.jackson.core:jackson-annotations) >= %{version}, mvn(com.fasterxml.jackson.core:jackson-core) >= %{version} @@ -50,5 +51,8 @@ sed -i 's/\r//' NOTICE LICENSE /usr/share/maven* %changelog +* Tue Mar 2 2021 zhanghua - 2.9.4-6 +- fix CVE-2020-28491 + * Sat Dec 7 2019 openEuler Buildteam - 2.9.4-5 - Package init -- Gitee