Prevent message truncation by populate function 70/1470/1
authorE. Scott Daniels <daniels@research.att.com>
Fri, 1 Nov 2019 13:24:08 +0000 (09:24 -0400)
committerE. Scott Daniels <daniels@research.att.com>
Mon, 11 Nov 2019 15:21:59 +0000 (10:21 -0500)
An attempt to write a payload to a received message in prep
for returning the response to sender could result in the
response message being truncated if it is longer than the
payload in the received message. The populate and set length
function was modified to ensure that the target message has
a payload length which is not less than the message being
added; if it does the message payload is reallocated through
RMR.

This change requires RMR version 1.10.2 or later.

Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Change-Id: I8fa26eaace814344481c2df715c7c2486a38f6df

src/bindings/rmr-python/docs/Changelog.rst
src/bindings/rmr-python/rmr-version.yaml
src/bindings/rmr-python/rmr/rmr.py
src/bindings/rmr-python/tests/test_rmr.py

index 3b29e66..4fa1629 100644 (file)
@@ -7,6 +7,13 @@ The format is based on `Keep a Changelog <http://keepachangelog.com/>`__
 and this project adheres to `Semantic
 Versioning <http://semver.org/>`__.
 
+[X.X.X] - 10/30/2019
+--------------------
+
+::
+    * This is a breaking change as it rquires that RMR version 1.10.2 or later be used.
+    * The populate and set length function will reallocate the message buffer payload if the caller attempts to insert more bytes than the currrent message supports.
+
 
 [1.0.0] - 10/24/2019
 --------------------
index 1ea7883..0d9c301 100644 (file)
@@ -1,3 +1,3 @@
 # CI script installs RMR from PackageCloud using this version
 ---
-version: 1.8.3
+version: 1.10.2
index 0265e21..99c2088 100644 (file)
@@ -1,3 +1,4 @@
+# vim: expandtab ts=4 sw=4:
 # ==================================================================================
 #       Copyright (c) 2019 Nokia
 #       Copyright (c) 2018-2019 AT&T Intellectual Property.
@@ -248,6 +249,19 @@ def rmr_alloc_msg(vctx, size, payload=None, gen_transaction_id=False, mtype=None
         raise BadBufferAllocation
 
 
+_rmr_realloc_payload = rmr_c_lib.rmr_realloc_payload
+_rmr_realloc_payload.argtypes = [POINTER(rmr_mbuf_t), c_int, c_int, c_int]  # new_len, copy, clone
+_rmr_realloc_payload.restype = POINTER(rmr_mbuf_t)
+
+
+def rmr_realloc_payload(ptr_mbuf, new_len, copy=False, clone=False):
+    """
+    Refer to the rmr C documentation for rmr_realloc_payload().
+    extern rmr_mbuf_t* rmr_realloc_payload(rmr_mbuf_t*, int, int, int)
+    """
+    return _rmr_realloc_payload(ptr_mbuf, new_len, copy, clone)
+
+
 _rmr_free_msg = rmr_c_lib.rmr_free_msg
 _rmr_free_msg.argtypes = [c_void_p]
 _rmr_free_msg.restype = None
@@ -256,7 +270,7 @@ _rmr_free_msg.restype = None
 def rmr_free_msg(mbuf):
     """
     Refer to the rmr C documentation for rmr_free_msg
-    extern void rmr_free_msg( rmr_mbuf_t* mbuf )
+    extern void rmr_free_msg(rmr_mbuf_t* mbuf )
     """
     if mbuf is not None:
         _rmr_free_msg(mbuf)
@@ -487,6 +501,9 @@ def set_payload_and_length(byte_str, ptr_mbuf):
     ptr_mbuf: ctypes c_void_p
         Pointer to an rmr message buffer
     """
+    if rmr_payload_size(ptr_mbuf) < len(byte_str):  # existing message payload too small
+        ptr_mbuf = rmr_realloc_payload(ptr_mbuf, len(byte_str), True)
+
     memmove(ptr_mbuf.contents.payload, byte_str, len(byte_str))
     ptr_mbuf.contents.len = len(byte_str)
 
index e43b170..cd07545 100644 (file)
@@ -287,3 +287,21 @@ def test_alloc_fancy():
     assert summary["message state"] == 0
     assert summary["message type"] == 14
     assert summary["meid"] == b"asdf"
+
+
+def test_resize_payload():
+    """test the ability to insert a larger payload into an existing message"""
+    mtype = 99
+    subid = 100
+
+    mbuf = rmr.rmr_alloc_msg(MRC_SEND, 25)  # allocate buffer with small payload
+    mbuf.contents.mtype = mtype             # type and sub-id should not change
+    mbuf.contents.sub_id = subid
+
+    long_payload = b"This is a long payload that should force the message buffer to be reallocated"
+    rmr.set_payload_and_length(long_payload, mbuf)
+    summary = rmr.message_summary(mbuf)
+    assert summary["payload max size"] >= len(long_payload)     # RMR may allocate a larger payload space
+    assert summary["payload length"] == len(long_payload)       # however, the length must be exactly the same
+    assert summary["message type"] == mtype                     # both mtype and sub-id should be preserved in new
+    assert summary["subscription id"] == subid