diff --git a/CHANGELOG.md b/CHANGELOG.md index 37a88e9..bf91b90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed + +- Invalid payload parsing when the message is broken. + ## [2.4.2] - 2024-01-18 ### Added diff --git a/membership.lua b/membership.lua index 087f9c8..9a00507 100755 --- a/membership.lua +++ b/membership.lua @@ -779,10 +779,17 @@ local function _member_pack(uri, member) return nil end + local payload = member.payload + if payload == msgpack.NULL + or type(payload) ~= 'table' + then + payload = {} + end + return { uri = uri, status = opts.STATUS_NAMES[member.status] or tostring(member.status), - payload = member.payload or {}, + payload = payload, incarnation = member.incarnation, timestamp = member.timestamp, clock_delta = member.clock_delta, @@ -934,6 +941,9 @@ local function set_payload(key, value) checks('string', '?') local myself = members.get(advertise_uri) local payload = myself.payload + if type(payload) ~= 'table' then + payload = {} + end if payload[key] == value then return true end diff --git a/membership/events.lua b/membership/events.lua index 95cca95..1bd884b 100644 --- a/membership/events.lua +++ b/membership/events.lua @@ -84,11 +84,17 @@ end function events.unpack(event) checks('table') + local payload = event[4] + if payload == msgpack.NULL + or type(payload) ~= 'table' + then + payload = nil + end return { - uri = event[1], - status = event[2], - incarnation = event[3], - payload = (event[4] ~= msgpack.NULL) and event[4] or nil, + uri = tostring(event[1]), + status = tonumber(event[2]), + incarnation = tonumber(event[3]), + payload = payload, ttl = event[5], } end diff --git a/membership/members.lua b/membership/members.lua index 6cdc045..43b520e 100644 --- a/membership/members.lua +++ b/membership/members.lua @@ -55,10 +55,16 @@ end function members.unpack(member) checks('table') + local payload = member[3] + if payload == msgpack.NULL + or type(payload) ~= 'table' + then + payload = nil + end return member[1], { - status = member[2], - incarnation = member[3], - payload = (member[4] ~= msgpack.NULL) and member[4] or nil, + status = tonumber(member[2]), + incarnation = tonumber(member[3]), + payload = payload, } end diff --git a/test/instance.lua b/test/instance.lua index e7eb17c..ce509cb 100755 --- a/test/instance.lua +++ b/test/instance.lua @@ -4,6 +4,15 @@ require('strict').on() local log = require('log') local fiber = require('fiber') local console = require('console') + +local checks = require('checks') +package.loaded['checks'] = function(...) + if rawget(_G, "checks_disabled") == true then + return + end + return checks(...) +end + local membership = require('membership') _G.membership = membership diff --git a/test/test_dissemination.py b/test/test_dissemination.py index 458ffdf..3a4d4b3 100644 --- a/test/test_dissemination.py +++ b/test/test_dissemination.py @@ -60,7 +60,7 @@ def test_discover_kill(servers, helpers): t1 = time.time() def check_public_opinion(): - """ Cheack that all members consider URI has given STATUS """ + """ Check that all members consider URI has given STATUS """ for port, srv in list(servers_copy.items()): member = srv.get_member(uri) diff --git a/test/test_payload.py b/test/test_payload.py index 2e38f18..af8cf66 100644 --- a/test/test_payload.py +++ b/test/test_payload.py @@ -4,9 +4,9 @@ servers_list = [13301, 13302] -def check_payload(srv, uri, payload): +def check_payload(srv, uri, payload, status='alive'): member = srv.members()[uri] - assert member['status'] == 'alive' + assert member['status'] == status assert member['payload'] == payload @@ -39,3 +39,18 @@ def test(servers, helpers): 'foo2': 42 } ]) + + assert servers[13301].conn.eval(''' + _G.checks_disabled = true + local opts = require('membership.options') + require('membership.events').generate('13301', opts.DEAD, 31, 37) + _G.checks_disabled = false + + return true + ''')[0] + helpers.wait_for(check_payload, [ + servers[13302], + '13301', + {}, + 'dead', + ])