aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2018-03-16 14:51:24 +0000
committerMatthew Wild <mwild1@gmail.com>2018-03-16 14:51:24 +0000
commit6d7cd57d44fced8c151a1ae010b5e24d9da02a89 (patch)
tree9f92c5b23cf04c6b18282fd4ff47cb52e4fc9391
parentb7fd84b6e54273b18362b51c0b8388bea0ddbbbf (diff)
downloadprosody-6d7cd57d44fced8c151a1ae010b5e24d9da02a89.tar.gz
prosody-6d7cd57d44fced8c151a1ae010b5e24d9da02a89.zip
util.stanza: Add stricter validation for data passed to stanza builder API
-rw-r--r--spec/util_stanza_spec.lua34
-rw-r--r--util/stanza.lua29
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;