diff --git a/spec/std/xml/xml_spec.cr b/spec/std/xml/xml_spec.cr index 9cac2051aef3..fb74b5e4288d 100644 --- a/spec/std/xml/xml_spec.cr +++ b/spec/std/xml/xml_spec.cr @@ -257,6 +257,31 @@ describe XML do root.name.should eq("last-name") end + it "doesn't set invalid node name" do + doc = XML.parse(<<-XML + + John + XML + ) + root = doc.root.not_nil! + + expect_raises(XML::Error, "Invalid node name") do + root.name = " foo bar" + end + + expect_raises(XML::Error, "Invalid node name") do + root.name = "foo bar" + end + + expect_raises(XML::Error, "Invalid node name") do + root.name = "1foo" + end + + expect_raises(XML::Error, "Invalid node name") do + root.name = "\0foo" + end + end + it "gets encoding" do doc = XML.parse(<<-XML diff --git a/src/xml/libxml2.cr b/src/xml/libxml2.cr index deb8942aba64..7d0acee20af9 100644 --- a/src/xml/libxml2.cr +++ b/src/xml/libxml2.cr @@ -294,6 +294,8 @@ lib LibXML fun xmlGetNsList(doc : Doc*, node : Node*) : NS** fun xmlSetProp(node : Node*, name : UInt8*, value : UInt8*) : Attr* + + fun xmlValidateNameValue(value : UInt8*) : Int end LibXML.xmlGcMemSetup( diff --git a/src/xml/node.cr b/src/xml/node.cr index 1c37693fc41a..b5bb9cf2bdd5 100644 --- a/src/xml/node.cr +++ b/src/xml/node.cr @@ -274,7 +274,18 @@ struct XML::Node if document? || text? || cdata? || fragment? raise XML::Error.new("Can't set name of XML #{type}", 0) end - LibXML.xmlNodeSetName(self, name.to_s) + + name = name.to_s + + if name.includes? '\0' + raise XML::Error.new("Invalid node name: #{name.inspect} (contains null character)") + end + + if LibXML.xmlValidateNameValue(name) == 0 + raise XML::Error.new("Invalid node name: #{name.inspect}", 0) + end + + LibXML.xmlNodeSetName(self, name) end # Returns the namespace for this node or `nil` if not found.