Projects
Mega:24.03:SP1:Everything
jackson-dataformats-binary
_service:tar_scm:CVE-2020-28491.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:CVE-2020-28491.patch of Package jackson-dataformats-binary
From de072d314af8f5f269c8abec6930652af67bc8e6 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta <tatu.saloranta@iki.fi> 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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2