From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 9E2AC6EC5D; Sun, 4 Apr 2021 18:07:48 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 9E2AC6EC5D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1617548868; bh=3qJKXSW57yoIzanb283TXtxE4l54GjY3ZPzZ4H560PY=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=LqEFN1paJYVkHoeya3GwksVe3id/Cbc4/RKVbg4OhlZOJP9J42D9Q3UbTXrTE/e9x 3znzh9S3PMoC8MOAUiEy2MPPthQRlaebZmUuXXO3mYFI00jK94szDgktRSsHzY8WV6 /jO5zMja04vfmIVUUvwQV2S8FyAAD0jI67AudOV0= Received: from smtpng1.m.smailru.net (smtpng1.m.smailru.net [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 81B126EC5D for ; Sun, 4 Apr 2021 18:06:47 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 81B126EC5D Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1lT4Ks-00088P-MB; Sun, 04 Apr 2021 18:06:47 +0300 To: tarantool-patches@dev.tarantool.org, gorcunov@gmail.com, sergepetrenko@tarantool.org Date: Sun, 4 Apr 2021 17:06:43 +0200 Message-Id: X-Mailer: git-send-email 2.24.3 (Apple Git-128) In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9ED7173E37F4E3294CA3588DDE0233B0D17711AF1EA2D7DB9182A05F5380850404A0190872F1F396FD3640385E56EFB8A4496268119EDB38340D52C120F6020BC X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE71DA217C11732C59FEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006370BEBC60587DC626C8638F802B75D45FF914D58D5BE9E6BC131B5C99E7648C95C16EE06F5A270FE6A0601B0E3F4325945B5E36933D4E6C215A471835C12D1D9774AD6D5ED66289B5259CC434672EE6371117882F4460429724CE54428C33FAD30A8DF7F3B2552694AC26CFBAC0749D213D2E47CDBA5A9658359CC434672EE6371117882F4460429728AD0CFFFB425014E868A13BD56FB6657E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F79006374EBA37F70F1BFF76EFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C16EE06F5A270FE6A0601B0E3F4325945B5E36933D4E6C2159C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF0417BEADF48D1460699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34A9A0A0BF1A2CAC62718D8D9A8A39E707F1DDC0B7F8E48DF546D3C738A7DAE25A29BB3970FE45FE4D1D7E09C32AA3244C41E5C2268117BA3FD120311572A8F200795D98D676DD64D0FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojt47dm/981n7wWB/PIdqbfQ== X-Mailru-Sender: 689FA8AB762F73936BC43F508A0638224A43DAFE7526A9FAF2EE5D2BE001311A3841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E267EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH 2/2] swim: check types in __serialize methods X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Vladislav Shpilevoy via Tarantool-patches Reply-To: Vladislav Shpilevoy Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" In swim Lua code none of the __serialize methods checked the argument type assuming that nobody would call them directly and mess with the types. But it happened, and is not hard to fix, so the patch does it. The serialization functions are sanitized for the swim object, swim member, and member event. Closes #5952 --- changelogs/unreleased/swim-serialize-crash.md | 4 + src/lua/swim.lua | 41 +++++-- test/swim/gh-5952-swim-serialize.result | 101 ++++++++++++++++++ test/swim/gh-5952-swim-serialize.test.lua | 33 ++++++ 4 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 changelogs/unreleased/swim-serialize-crash.md create mode 100644 test/swim/gh-5952-swim-serialize.result create mode 100644 test/swim/gh-5952-swim-serialize.test.lua diff --git a/changelogs/unreleased/swim-serialize-crash.md b/changelogs/unreleased/swim-serialize-crash.md new file mode 100644 index 000000000..e48b1f518 --- /dev/null +++ b/changelogs/unreleased/swim-serialize-crash.md @@ -0,0 +1,4 @@ +## bugfix/swim + +* Fix the crash on an attempt to pass an object of a wrong type to `__serialize` + method of a swim member in Lua (gh-5952). diff --git a/src/lua/swim.lua b/src/lua/swim.lua index f61aa6b58..027f07038 100644 --- a/src/lua/swim.lua +++ b/src/lua/swim.lua @@ -322,6 +322,16 @@ local function swim_check_member(m, func_name) return error(func_name..': first argument is not a SWIM member') end +local function swim_check_event(event, func_name) + if type(event) == 'table' then + local value = event[1] + if type(value) == 'number' then + return value + end + end + return error(func_name..': first argument is not a SWIM event') +end + -- -- Member methods. Most of them are one-liners, not much to -- comment. @@ -435,7 +445,8 @@ local function swim_member_uuid(m) end local function swim_member_serialize(m) - local _, size = swim_member_payload_raw(m.ptr) + local ptr = swim_check_member(m, 'member:__serialize()') + local _, size = swim_member_payload_raw(ptr) return { status = swim_member_status(m), uuid = swim_member_uuid(m), @@ -543,6 +554,7 @@ end -- serialized, for example, in a console. -- local function swim_serialize(s) + swim_check_instance(s, 'swim:__serialize()') return s.cfg.index end @@ -739,31 +751,40 @@ end local swim_member_event_index = { is_new = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW) ~= 0 + local value = swim_check_event(self, 'event:is_new()') + return bit.band(value, capi.SWIM_EV_NEW) ~= 0 end, is_drop = function(self) - return bit.band(self[1], capi.SWIM_EV_DROP) ~= 0 + local value = swim_check_event(self, 'event:is_drop()') + return bit.band(value, capi.SWIM_EV_DROP) ~= 0 end, is_update = function(self) - return bit.band(self[1], capi.SWIM_EV_UPDATE) ~= 0 + local value = swim_check_event(self, 'event:is_update()') + return bit.band(value, capi.SWIM_EV_UPDATE) ~= 0 end, is_new_status = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW_STATUS) ~= 0 + local value = swim_check_event(self, 'event:is_new_status()') + return bit.band(value, capi.SWIM_EV_NEW_STATUS) ~= 0 end, is_new_uri = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW_URI) ~= 0 + local value = swim_check_event(self, 'event:is_new_uri()') + return bit.band(value, capi.SWIM_EV_NEW_URI) ~= 0 end, is_new_incarnation = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW_INCARNATION) ~= 0 + local value = swim_check_event(self, 'event:is_new_incarnation()') + return bit.band(value, capi.SWIM_EV_NEW_INCARNATION) ~= 0 end, is_new_generation = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW_GENERATION) ~= 0 + local value = swim_check_event(self, 'event:is_new_generation()') + return bit.band(value, capi.SWIM_EV_NEW_GENERATION) ~= 0 end, is_new_version = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW_VERSION) ~= 0 + local value = swim_check_event(self, 'event:is_new_version()') + return bit.band(value, capi.SWIM_EV_NEW_VERSION) ~= 0 end, is_new_payload = function(self) - return bit.band(self[1], capi.SWIM_EV_NEW_PAYLOAD) ~= 0 + local value = swim_check_event(self, 'event:is_new_payload()') + return bit.band(value, capi.SWIM_EV_NEW_PAYLOAD) ~= 0 end, } diff --git a/test/swim/gh-5952-swim-serialize.result b/test/swim/gh-5952-swim-serialize.result new file mode 100644 index 000000000..0f9c3250b --- /dev/null +++ b/test/swim/gh-5952-swim-serialize.result @@ -0,0 +1,101 @@ +-- test-run result file version 2 +fiber = require('fiber') + | --- + | ... +swim = require('swim') + | --- + | ... +test_run = require('test_run').new() + | --- + | ... +test_run:cmd("push filter '\\.lua.*:[0-9]+: ' to '.lua:: '") + | --- + | - true + | ... +test_run:cmd("push filter '127.0.0.1:[0-9]+$' to '127.0.0.1:'") + | --- + | - true + | ... + +-- +-- gh-5952: invalid types in __serialize methods could lead to a crash. +-- + +s = swim.new({generation = 0}) + | --- + | ... +getmetatable(s):__serialize() + | --- + | - error: 'builtin/swim.lua:: swim:__serialize(): first argument is not a SWIM instance' + | ... +getmetatable(s).__serialize(s) + | --- + | - [] + | ... + +s:cfg({uuid = uuid(1), uri = uri()}) + | --- + | - true + | ... +getmetatable(s):__serialize() + | --- + | - error: 'builtin/swim.lua:: swim:__serialize(): first argument is not a SWIM instance' + | ... +getmetatable(s).__serialize(s) + | --- + | - uuid: 00000000-0000-1000-8000-000000000001 + | uri: 127.0.0.1: + | ... + +self = s:self() + | --- + | ... +getmetatable(self):__serialize() + | --- + | - error: 'builtin/swim.lua:: member:__serialize(): first argument is not a SWIM + | member' + | ... +getmetatable(self).__serialize(self) + | --- + | - uri: 127.0.0.1: + | status: alive + | incarnation: cdata {generation = 0ULL, version = 1ULL} + | uuid: 00000000-0000-1000-8000-000000000001 + | payload_size: 0 + | ... + +event = nil + | --- + | ... +_ = s:on_member_event(function(m, e) event = e end) + | --- + | ... +s:set_payload(1) + | --- + | - true + | ... +test_run:wait_cond(function() return event ~= nil end) + | --- + | - true + | ... + +getmetatable(event):__serialize() + | --- + | - error: 'builtin/swim.lua:: event:is_update(): first argument is not a SWIM event' + | ... +getmetatable(event).__serialize(event) + | --- + | - is_new_payload: true + | is_new_version: true + | is_new_incarnation: true + | is_update: true + | ... + +s:delete() + | --- + | ... + +test_run:cmd("clear filter") + | --- + | - true + | ... diff --git a/test/swim/gh-5952-swim-serialize.test.lua b/test/swim/gh-5952-swim-serialize.test.lua new file mode 100644 index 000000000..7bf75ba4f --- /dev/null +++ b/test/swim/gh-5952-swim-serialize.test.lua @@ -0,0 +1,33 @@ +fiber = require('fiber') +swim = require('swim') +test_run = require('test_run').new() +test_run:cmd("push filter '\\.lua.*:[0-9]+: ' to '.lua:: '") +test_run:cmd("push filter '127.0.0.1:[0-9]+$' to '127.0.0.1:'") + +-- +-- gh-5952: invalid types in __serialize methods could lead to a crash. +-- + +s = swim.new({generation = 0}) +getmetatable(s):__serialize() +getmetatable(s).__serialize(s) + +s:cfg({uuid = uuid(1), uri = uri()}) +getmetatable(s):__serialize() +getmetatable(s).__serialize(s) + +self = s:self() +getmetatable(self):__serialize() +getmetatable(self).__serialize(self) + +event = nil +_ = s:on_member_event(function(m, e) event = e end) +s:set_payload(1) +test_run:wait_cond(function() return event ~= nil end) + +getmetatable(event):__serialize() +getmetatable(event).__serialize(event) + +s:delete() + +test_run:cmd("clear filter") -- 2.24.3 (Apple Git-128)