lutaml-model 0.8.62 → 0.8.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e60ce4a1bedec13a3b778b0afea4c9be5c4779f721916bfafeb151e3bd8f8c1e
|
|
4
|
+
data.tar.gz: b6f519fabe6c9dc9c0c5edeb871d6afcc23d6439eff433b15b74b532b1a633d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 646c4cfdfb4dc395f5f339332eb214b0d4cba7bf31710884357e5d8519db8825e0a8e937824f268bac8642ea5d23a7fee75686988b9d3a54923f508e50aaa3c0
|
|
7
|
+
data.tar.gz: d738e9c618790d6575691acc7349991f1b4f28986947e75a3dc40a883978cbc3ce7f6ef28021b7c85f822037c6c63137ed22f1930fe6aba36dd0b266f84a451b
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -20,6 +20,7 @@ module Lutaml
|
|
|
20
20
|
raw_xml = xml
|
|
21
21
|
xml = normalize_xml_for_parse(xml)
|
|
22
22
|
parsed = parse_with_moxml(xml, parse_encoding)
|
|
23
|
+
assert_no_truncated_recovered_parse!(parsed)
|
|
23
24
|
root_element = parsed.root
|
|
24
25
|
|
|
25
26
|
raise_empty_document_error if root_element.nil?
|
|
@@ -30,6 +31,25 @@ module Lutaml
|
|
|
30
31
|
new(root, parse_encoding, **parse_document_options(raw_xml))
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
# Recover-mode parsing must never masquerade input truncation as
|
|
35
|
+
# success.
|
|
36
|
+
#
|
|
37
|
+
# libxml2 (the Nokogiri backend) caps its input buffer at 10 MB;
|
|
38
|
+
# longer documents trip a fatal "Resource limit exceeded: Buffer
|
|
39
|
+
# size limit exceeded, try XML_PARSE_HUGE" error mid-input. In
|
|
40
|
+
# recover mode Nokogiri records that error on the document and
|
|
41
|
+
# returns the partial tree, so every node past the limit silently
|
|
42
|
+
# vanishes (lutaml-model#871). A resource-limit fatal means the
|
|
43
|
+
# engine stopped early with input left — refuse to deserialize the
|
|
44
|
+
# partial document instead of dropping trailing content without a
|
|
45
|
+
# trace.
|
|
46
|
+
#
|
|
47
|
+
# Other recover-mode fatals (e.g. an XML declaration after leading
|
|
48
|
+
# whitespace) do not drop content and keep the long-standing
|
|
49
|
+
# recover behavior; only the resource-limit family is truncating.
|
|
50
|
+
TRUNCATION_FATAL_MARKER =
|
|
51
|
+
/Resource limit exceeded|Buffer size limit exceeded/
|
|
52
|
+
|
|
33
53
|
private
|
|
34
54
|
|
|
35
55
|
def normalize_xml_for_parse(xml)
|
|
@@ -62,6 +82,23 @@ module Lutaml
|
|
|
62
82
|
end
|
|
63
83
|
end
|
|
64
84
|
|
|
85
|
+
def assert_no_truncated_recovered_parse!(parsed)
|
|
86
|
+
errors = parsed.parse_errors
|
|
87
|
+
return if errors.nil? || errors.empty?
|
|
88
|
+
|
|
89
|
+
fatal = errors.find do |message|
|
|
90
|
+
message.match?(TRUNCATION_FATAL_MARKER)
|
|
91
|
+
end
|
|
92
|
+
return if fatal.nil?
|
|
93
|
+
|
|
94
|
+
raise Lutaml::Model::InvalidFormatError.new(
|
|
95
|
+
:xml,
|
|
96
|
+
"the XML engine reported a fatal resource limit and recovered " \
|
|
97
|
+
"with a truncated document; refusing to deserialize " \
|
|
98
|
+
"partial input (#{fatal})",
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
|
|
65
102
|
def parse_document_options(xml)
|
|
66
103
|
{
|
|
67
104
|
doctype: extract_doctype_from_xml(xml),
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "nokogiri"
|
|
5
|
+
require "lutaml/model"
|
|
6
|
+
require "lutaml/xml"
|
|
7
|
+
require "lutaml/xml/adapter/nokogiri_adapter"
|
|
8
|
+
|
|
9
|
+
# Regression tests for lutaml-model#871.
|
|
10
|
+
#
|
|
11
|
+
# libxml2 (the Nokogiri backend) caps its input buffer at 10 MB. Parsing a
|
|
12
|
+
# longer document in recover mode records a FATAL "Resource limit exceeded:
|
|
13
|
+
# Buffer size limit exceeded, try XML_PARSE_HUGE" error on the document and
|
|
14
|
+
# returns the partial tree, so every node past the cap silently vanishes.
|
|
15
|
+
# XmlParser now refuses documents whose parse_errors carry a fatal error
|
|
16
|
+
# instead of deserializing the truncated input.
|
|
17
|
+
RSpec.describe "recovered fatal parse errors" do
|
|
18
|
+
let(:annex_class) do
|
|
19
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
20
|
+
attribute :id, :string
|
|
21
|
+
|
|
22
|
+
xml do
|
|
23
|
+
element "annex"
|
|
24
|
+
map_attribute "id", to: :id
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let(:root_class) do
|
|
30
|
+
annex = annex_class
|
|
31
|
+
|
|
32
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
33
|
+
attribute :annexes, annex, collection: true
|
|
34
|
+
|
|
35
|
+
xml do
|
|
36
|
+
element "metanorma"
|
|
37
|
+
map_element "annex", to: :annexes
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def build_document(chunk_count:, chunk_size:, with_tail: false)
|
|
43
|
+
filler = "A" * chunk_size
|
|
44
|
+
document = +"<metanorma>"
|
|
45
|
+
chunk_count.times do |index|
|
|
46
|
+
document << %(<annex id="annex#{index}" data="#{filler}"/>)
|
|
47
|
+
end
|
|
48
|
+
document << %(<annex id="annex-tail-marker"/>) if with_tail
|
|
49
|
+
document << "</metanorma>"
|
|
50
|
+
document
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Six 1.7 MB attribute values push the cumulative input past libxml2's
|
|
54
|
+
# 10 MB buffer cap mid-document, mirroring the issue's failing manifest.
|
|
55
|
+
def over_cap_document
|
|
56
|
+
build_document(chunk_count: 6, chunk_size: 1_700_000, with_tail: true)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "hits the libxml2 buffer cap in recover mode past 10 MB" do
|
|
60
|
+
errors = Nokogiri::XML(over_cap_document) { |config| config.recover.nonet }.errors
|
|
61
|
+
|
|
62
|
+
expect(errors.map(&:message).join("\n")).to match(/\bFATAL:/)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "raises instead of silently truncating on the nokogiri path" do
|
|
66
|
+
Lutaml::Model::Config.with_adapter(xml: :nokogiri) do
|
|
67
|
+
expect { root_class.from_xml(over_cap_document) }
|
|
68
|
+
.to raise_error(Lutaml::Model::InvalidFormatError, /resource limit.*truncated/m)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "raises from the adapter layer directly" do
|
|
73
|
+
Lutaml::Model::Config.with_adapter(xml: :nokogiri) do
|
|
74
|
+
expect { Lutaml::Xml::Adapter::NokogiriAdapter.parse(over_cap_document) }
|
|
75
|
+
.to raise_error(Lutaml::Model::InvalidFormatError, /XML_PARSE_HUGE/)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "keeps parsing documents whose fatals do not drop content" do
|
|
80
|
+
xml = " <?xml version=\"1.0\"?>\n<metanorma><annex id=\"a\"/></metanorma>"
|
|
81
|
+
|
|
82
|
+
Lutaml::Model::Config.with_adapter(xml: :nokogiri) do
|
|
83
|
+
model = root_class.from_xml(xml)
|
|
84
|
+
|
|
85
|
+
expect(model.annexes.map(&:id)).to eq(["a"])
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "still parses smaller documents without any fatal-error handling" do
|
|
90
|
+
Lutaml::Model::Config.with_adapter(xml: :nokogiri) do
|
|
91
|
+
model = root_class.from_xml(
|
|
92
|
+
build_document(chunk_count: 2, chunk_size: 500_000, with_tail: true),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
expect(model.annexes.map(&:id))
|
|
96
|
+
.to eq(["annex0", "annex1", "annex-tail-marker"])
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lutaml-model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.63
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -1902,6 +1902,7 @@ files:
|
|
|
1902
1902
|
- spec/lutaml/xml/adapter/oga_adapter_spec.rb
|
|
1903
1903
|
- spec/lutaml/xml/adapter/order_spec.rb
|
|
1904
1904
|
- spec/lutaml/xml/adapter/ox_adapter_spec.rb
|
|
1905
|
+
- spec/lutaml/xml/adapter/recovered_fatal_parse_spec.rb
|
|
1905
1906
|
- spec/lutaml/xml/adapter/rexml_adapter_spec.rb
|
|
1906
1907
|
- spec/lutaml/xml/adapter/xml_namespace_spec.rb
|
|
1907
1908
|
- spec/lutaml/xml/adapter_loader_spec.rb
|