Skip to content

Commit 27bad62

Browse files
authored
Fix: safe-guard byte buf allocation (#420)
since `inflateCompressedFrame` might have leaked, see #408
1 parent ab0667a commit 27bad62

File tree

4 files changed

+38
-23
lines changed

4 files changed

+38
-23
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
## Unreleased
1+
## 6.1.3
2+
- Fix: safe-guard byte buf allocation [#420](https://github.com/logstash-plugins/logstash-input-beats/pull/420)
23
- Updated Jackson dependencies
34

45
## 6.1.2
@@ -13,7 +14,7 @@
1314
`host` and `@metadata.ip_address` event fields. [#404](https://github.com/logstash-plugins/logstash-input-beats/pull/404)
1415

1516
## 6.0.14
16-
- Feat: log + unwrap generic SSL context exceptions [#405](https://github.com/logstash-plugins/logstash-input-beats/pull/405)
17+
- Feat: log + unwrap generic SSL context exceptions [#405](https://github.com/logstash-plugins/logstash-input-beats/pull/405)
1718

1819
## 6.0.13
1920
- [DOC] Update links to use shared attributes

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6.1.2
1+
6.1.3

src/main/java/org/logstash/beats/BeatsParser.java

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ private enum States {
4747
private boolean decodingCompressedBuffer = false;
4848

4949
@Override
50-
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
50+
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws InvalidFrameProtocolException, IOException {
5151
if(!hasEnoughBytes(in)) {
5252
if (decodingCompressedBuffer){
5353
throw new InvalidFrameProtocolException("Insufficient bytes in compressed content to decode: " + currentState);
@@ -124,7 +124,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) t
124124
int fieldsCount = (int) in.readUnsignedInt();
125125
int count = 0;
126126

127-
if(fieldsCount <= 0) {
127+
if (fieldsCount <= 0) {
128128
throw new InvalidFrameProtocolException("Invalid number of fields, received: " + fieldsCount);
129129
}
130130

@@ -178,20 +178,19 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) t
178178

179179
case READ_COMPRESSED_FRAME: {
180180
logger.trace("Running: READ_COMPRESSED_FRAME");
181-
// Use the compressed size as the safe start for the buffer.
182-
ByteBuf buffer = inflateCompressedFrame(ctx, in);
183-
transition(States.READ_HEADER);
181+
inflateCompressedFrame(ctx, in, (buffer) -> {
182+
transition(States.READ_HEADER);
184183

185-
decodingCompressedBuffer = true;
186-
try {
187-
while (buffer.readableBytes() > 0) {
188-
decode(ctx, buffer, out);
184+
decodingCompressedBuffer = true;
185+
try {
186+
while (buffer.readableBytes() > 0) {
187+
decode(ctx, buffer, out);
188+
}
189+
} finally {
190+
decodingCompressedBuffer = false;
191+
transition(States.READ_HEADER);
189192
}
190-
} finally {
191-
decodingCompressedBuffer = false;
192-
buffer.release();
193-
transition(States.READ_HEADER);
194-
}
193+
});
195194
break;
196195
}
197196
case READ_JSON: {
@@ -211,18 +210,28 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) t
211210
}
212211
}
213212

214-
private ByteBuf inflateCompressedFrame(final ChannelHandlerContext ctx, final ByteBuf in) throws IOException {
213+
private void inflateCompressedFrame(final ChannelHandlerContext ctx, final ByteBuf in, final CheckedConsumer<ByteBuf> fn)
214+
throws IOException {
215+
// Use the compressed size as the safe start for the buffer.
215216
ByteBuf buffer = ctx.alloc().buffer(requiredBytes);
217+
try {
218+
decompressImpl(in, buffer);
219+
fn.accept(buffer);
220+
} finally {
221+
buffer.release();
222+
}
223+
}
224+
225+
private void decompressImpl(final ByteBuf in, final ByteBuf out) throws IOException {
216226
Inflater inflater = new Inflater();
217227
try (
218-
ByteBufOutputStream buffOutput = new ByteBufOutputStream(buffer);
228+
ByteBufOutputStream buffOutput = new ByteBufOutputStream(out);
219229
InflaterOutputStream inflaterStream = new InflaterOutputStream(buffOutput, inflater)
220230
) {
221231
in.readBytes(inflaterStream, requiredBytes);
222-
}finally{
232+
} finally {
223233
inflater.end();
224234
}
225-
return buffer;
226235
}
227236

228237
private boolean hasEnoughBytes(ByteBuf in) {
@@ -234,7 +243,7 @@ private void transition(States next) {
234243
}
235244

236245
private void transition(States nextState, int requiredBytes) {
237-
if(logger.isTraceEnabled()) {
246+
if (logger.isTraceEnabled()) {
238247
logger.trace("Transition, from: " + currentState + ", to: " + nextState + ", requiring " + requiredBytes + " bytes");
239248
}
240249
this.currentState = nextState;
@@ -247,4 +256,9 @@ private void batchComplete() {
247256
batch = null;
248257
}
249258

259+
@FunctionalInterface
260+
private interface CheckedConsumer<T> {
261+
void accept(T t) throws IOException;
262+
}
263+
250264
}

src/main/java/org/logstash/beats/InvalidFrameProtocolException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.logstash.beats;
22

3-
public class InvalidFrameProtocolException extends Exception {
3+
public class InvalidFrameProtocolException extends RuntimeException {
44
InvalidFrameProtocolException(String message) {
55
super(message);
66
}

0 commit comments

Comments
 (0)