diff options
author | Matthew Wild <mwild1@gmail.com> | 2018-03-16 14:51:24 +0000 |
---|---|---|
committer | Matthew Wild <mwild1@gmail.com> | 2018-03-16 14:51:24 +0000 |
commit | d0a4392817106074a0470a6039f024baa593c748 (patch) | |
tree | 9f92c5b23cf04c6b18282fd4ff47cb52e4fc9391 | |
parent | 6d97f869e8dc7c148b5cc196f3e83ebc9bf72ca0 (diff) | |
download | prosody-d0a4392817106074a0470a6039f024baa593c748.tar.gz prosody-d0a4392817106074a0470a6039f024baa593c748.zip |
util.stanza: Add stricter validation for data passed to stanza builder API
-rw-r--r-- | spec/util_stanza_spec.lua | 34 | ||||
-rw-r--r-- | util/stanza.lua | 29 |
2 files changed, 63 insertions, 0 deletions
diff --git a/spec/util_stanza_spec.lua b/spec/util_stanza_spec.lua index 7543ffe7..ea3ef4c9 100644 --- a/spec/util_stanza_spec.lua +++ b/spec/util_stanza_spec.lua @@ -164,4 +164,38 @@ describe("util.stanza", function() assert.are.equal(r.tags[1].tags[1].name, "service-unavailable"); end); end); + + describe("#invalid", function () + it("name should be rejected", function () + assert.has_error(function () + st.stanza(1234); + end); + assert.has_error(function () + st.stanza({}); + end); + assert.has_error(function () + st.stanza(); + end); + assert.has_error(function () + st.stanza(""); + end); + assert.has_error(function () + st.stanza(string.char(0xC0)); + end); + assert.has_error(function () + st.stanza(string.char(0xF4, 0x90, 0x80, 0x80)); + end); + assert.has_error(function () + st.stanza("<>"); + end); + assert.has_error(function () + st.stanza("&"); + end); + end); + it("UTF-8 should be rejected", function () + assert.has_error(function () + st.stanza("tag"):text("hello "..string.char(0xF4, 0x90, 0x80, 0x80).." world"); + end); + end); + end); end); diff --git a/util/stanza.lua b/util/stanza.lua index a593a49b..50dc32bb 100644 --- a/util/stanza.lua +++ b/util/stanza.lua @@ -7,6 +7,7 @@ -- +local assert = assert; local t_insert = table.insert; local t_remove = table.remove; local t_concat = table.concat; @@ -23,6 +24,8 @@ local s_sub = string.sub; local s_find = string.find; local os = os; +local valid_utf8 = require "util.encodings".utf8.valid; + local do_pretty_printing = not os.getenv("WINDIR"); local getstyle, getstring; if do_pretty_printing then @@ -42,7 +45,32 @@ local _ENV = nil; local stanza_mt = { __name = "stanza" }; stanza_mt.__index = stanza_mt; +local function check_name(name) + assert(type(name) == "string", "tag name is not a string, "..type(name)); + assert(#name > 0, "tag name is empty"); + assert(not s_find(name, "[<>& '\"]"), "tag name contains invalid characters"); + assert(valid_utf8(name), "tag name is invalid utf8"); +end +local function check_attr(attr) + if attr ~= nil then + assert(type(attr) == "table", "attribute is not a table"); + for k, v in pairs(attr) do + assert(type(k) == "string", "non-string key in attributes"); + assert(valid_utf8(k), "attribute name is not valid utf8"); + assert(type(v) == "string", "non-string value in attributes"); + assert(valid_utf8(v), "attribute value is not valid utf8"); + end + end +end +local function check_text(text) + assert(type(text) == "string", "text is not a string"); + assert(valid_utf8(text), "text is not valid utf8"); +end + local function new_stanza(name, attr, namespaces) + assert(name) + check_name(name); + check_attr(attr); local stanza = { name = name, attr = attr or {}, namespaces = namespaces, tags = {} }; return setmetatable(stanza, stanza_mt); end @@ -69,6 +97,7 @@ function stanza_mt:tag(name, attr, namespaces) end function stanza_mt:text(text) + check_text(text); local last_add = self.last_add; (last_add and last_add[#last_add] or self):add_direct_child(text); return self; |