# Hardened XML parsing. What these tests pin down is documented at the top of # R/xmlsafe.R: neither XXE nor billion laughs works against xml2's defaults, # but both defences depend on defaults staying defaults. This file is what # turns that from an accident into a contract. test_that("entity declarations are rejected", { bomb <- paste0( '', '', ']>&lol2;' ) expect_error(arg_read_xml(bomb), class = "argentum_error_xml") # Case and internal whitespace do not dodge the check. expect_error( arg_read_xml(']>'), class = "argentum_error_xml" ) }) test_that("an external entity declaration is rejected before parsing", { xxe <- paste0( '', ']>', '&xxe;' ) expect_error(arg_read_xml(xxe), class = "argentum_error_xml") }) test_that("a bare DOCTYPE without entities still parses", { # WFS 1.0.0 / WMS 1.1.1 capabilities legitimately declare the OGC DTD. doc <- paste0( '', '', 'ok', '' ) parsed <- arg_read_xml(doc) expect_s3_class(parsed, "xml_document") expect_equal(xml2::xml_attr(xml2::xml_root(parsed), "version"), "1.1.1") }) test_that("a normal capabilities document does not trip the detection", { doc <- '' expect_s3_class(arg_read_xml(doc), "xml_document") }) test_that("oversized documents are rejected", { expect_error( arg_read_xml("abc", max_bytes = 5), class = "argentum_error_xml" ) # The cap is measured in bytes, not characters. expect_error( arg_read_xml("รกรกรกรก", max_bytes = 10), class = "argentum_error_xml" ) }) test_that("broken XML raises the package's own error class", { expect_error(arg_read_xml("this is not xml"), class = "argentum_error_xml") expect_error(arg_read_xml(""), class = "argentum_error_xml") })