From 13af188bdc55aba99f0c02dbcbce59ee6ace5351 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 10 Mar 2014 22:07:39 -0400 Subject: [PATCH] Handle invalid STOMP content-length header value After this change if a content-length header is provided but is less than 0 or cannot be parsed as a number, it is ignored and the body is read sequentially, i.e. until we reach a null byte terminator. This provides better protection against clients that may set the content-length header in error. Issue: SPR-11528 --- .../messaging/simp/stomp/StompDecoder.java | 17 +++++++--- .../messaging/simp/stomp/StompCodecTests.java | 32 ++++++++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java index cc3166e8ce..b644964946 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; /** * Decodes STOMP frames from a {@link ByteBuffer}. If the buffer does not contain @@ -151,9 +152,17 @@ public class StompDecoder { } private byte[] readPayload(ByteBuffer buffer, MultiValueMap headers) { - String contentLengthString = headers.getFirst("content-length"); - if (contentLengthString != null) { - int contentLength = Integer.valueOf(contentLengthString); + Integer contentLength = null; + if (headers.containsKey("content-length")) { + String rawContentLength = headers.getFirst("content-length"); + try { + contentLength = Integer.valueOf(rawContentLength); + } + catch (NumberFormatException ex) { + logger.warn("Ignoring invalid content-length header value: '" + rawContentLength + "'"); + } + } + if (contentLength != null && contentLength >= 0) { if (buffer.remaining() > contentLength) { byte[] payload = new byte[contentLength]; buffer.get(payload); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java index cf4939351b..0bf6f591a8 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -107,6 +107,36 @@ public class StompCodecTests { assertEquals("The body of the message", bodyText); } + // SPR-11528 + + @Test + public void decodeFrameWithInvalidContentLength() { + Message frame = decode("SEND\ncontent-length:-1\n\nThe body of the message\0"); + StompHeaderAccessor headers = StompHeaderAccessor.wrap(frame); + + assertEquals(StompCommand.SEND, headers.getCommand()); + + assertEquals(1, headers.toStompHeaderMap().size()); + assertEquals(Integer.valueOf(-1), headers.getContentLength()); + + String bodyText = new String(frame.getPayload()); + assertEquals("The body of the message", bodyText); + } + + @Test + public void decodeFrameWithContentLengthZero() { + Message frame = decode("SEND\ncontent-length:0\n\n\0"); + StompHeaderAccessor headers = StompHeaderAccessor.wrap(frame); + + assertEquals(StompCommand.SEND, headers.getCommand()); + + assertEquals(1, headers.toStompHeaderMap().size()); + assertEquals(Integer.valueOf(0), headers.getContentLength()); + + String bodyText = new String(frame.getPayload()); + assertEquals("", bodyText); + } + @Test public void decodeFrameWithNullOctectsInTheBody() { Message frame = decode("SEND\ncontent-length:23\n\nThe b\0dy \0f the message\0");