leptris 1.9.388.0-arm-linux → 1.9.390.0-arm-linux
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/Rakefile +1 -1
- data/lib/leptris/version.rb +1 -1
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +37 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/leptris/xpath/evaluator_axes.c +1 -1
- data/vendor-src/libleptris/src/leptris/xsd/compile.c +11 -2
- data/vendor-src/libleptris/src/leptris/xsd/content_model.c +94 -1
- data/vendor-src/libleptris/src/leptris/xsd/validate.c +13 -0
- data/vendor-src/libleptris/test/parser/test_parser.cpp +32 -0
- data/vendor-src/libleptris/test/xsd/test_xsd_compile.cpp +56 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1f6473ab1e7001f70f7bd3fe14cdf1da1e0debb40f498103bbb91d68a176e68
|
|
4
|
+
data.tar.gz: 2e45d0158274323e9f47d089671e3a2761b24769f052934c8146947453fdd4f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef0f1ebea3d784ea055059fa2500c755fa7d9416c2bafb8b641e373511705a83abfb156734574c1cb1b91cfb915d9729a0c298f84a8dc89ce4eb80bd2096b24a
|
|
7
|
+
data.tar.gz: 1ed6d494a872ac9f99c2956dce51853a2ea5a3c752ae47c0d145b39d3ee94cb5ae90df0f5f7bea971286a5f7cdacac934b921a07b29535cdceca42eccc2440d6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
### Changed — 1.9.389.0 (rides libleptris 1.9.389)
|
|
4
|
+
|
|
5
|
+
- Engine pin 1.9.388 -> 1.9.389: the XSD content-model automaton
|
|
6
|
+
size cap (leptris/leptris#1897, #1894 — pathological occurrence
|
|
7
|
+
products reject in microseconds via an analytic product bound,
|
|
8
|
+
with a 1e6 expansion cap backstop; over-cap models fail loudly
|
|
9
|
+
through the structured rows).
|
|
10
|
+
|
|
3
11
|
### Changed — 1.9.388.0 (rides libleptris 1.9.388)
|
|
4
12
|
|
|
5
13
|
- Engine pin 1.9.386 -> 1.9.388: carries the one-pass text-run scan
|
data/Rakefile
CHANGED
|
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
|
8
8
|
# Pin for `rake compile` and the platform-gem builds. Keep in lockstep
|
|
9
9
|
# with .github/workflows/build.yml (which calls `rake compile`) and the
|
|
10
10
|
# CHANGELOG when libleptris releases.
|
|
11
|
-
LIBLEPTRIS_VERSION = "1.9.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.390"
|
|
12
12
|
# Vendored alongside libleptris for fn:normalize-unicode (TODO
|
|
13
13
|
# .restructure/20): built per platform with a RELOCATABLE @rpath
|
|
14
14
|
# install name, loaded by ffi.rb before libleptris so the
|
data/lib/leptris/version.rb
CHANGED
data/lib/libleptris.so
CHANGED
|
Binary file
|
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.390] - 2026-10-29
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **XPath: compare `node->type` against its own enum constant
|
|
8
|
+
(leptris#1902).** The parent-axis attribute check (#1866,
|
|
9
|
+
`./@id/..`) used `LEPTRIS_NODE_ATTRIBUTE` — a constant of the
|
|
10
|
+
*other* internal enum — against `node->type`: same value, wrong
|
|
11
|
+
type. Found by the leptris-ts CI zero-warning gate (emcc
|
|
12
|
+
`-Wenum-compare`, wasm32 portability class).
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## [1.9.389] - 2026-10-29
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **XSD: size-cap the content-model automaton (leptris#1897,
|
|
21
|
+
leptris#1894).** A counted particle multiplies the expanded NFA
|
|
22
|
+
(finite `maxOccurs` copies the subtree per copy), so nested large
|
|
23
|
+
bounds grew the automaton exponentially and a huge finite bound
|
|
24
|
+
walked the copy loop until the process died — jetsam/OOM with no
|
|
25
|
+
diagnostic, which read as a flaky harness in the W3C XML Schema
|
|
26
|
+
Test Suite batch runner. Two layers: an analytic, saturating
|
|
27
|
+
product bound computed BEFORE the build rejects pathological
|
|
28
|
+
models in microseconds (the 2000x2000 repro measured 10.0s ->
|
|
29
|
+
0ms), and a 1e6 state/transition expansion cap as the backstop
|
|
30
|
+
for shapes the walk cannot see (cyclic groups). Over-cap models
|
|
31
|
+
fail LOUDLY: a `content-model` structured row on instance
|
|
32
|
+
validation and a `-1` (not evaluable) from the public
|
|
33
|
+
`leptris_xsd_content_valid` with the message on
|
|
34
|
+
`leptris_xsd_error`. The issue's own repro (seq maxOccurs=100 x
|
|
35
|
+
element unbounded) lowers to a ~200-state loop model and pins
|
|
36
|
+
green.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
3
40
|
## [1.9.388] - 2026-10-29
|
|
4
41
|
|
|
5
42
|
### Fixed
|
|
@@ -760,7 +760,7 @@ XPathNodeSet* apply_axis(XPathContext* ctx, LeptrisNode* node,
|
|
|
760
760
|
* element). The element-typed dispatch below would read the
|
|
761
761
|
* parent field in element form off the attribute struct and
|
|
762
762
|
* return empty (leptris#1866, the standoc svg-uniqueids face). */
|
|
763
|
-
if (axis_id == XPATH_AXIS_PARENT && node && node->type ==
|
|
763
|
+
if (axis_id == XPATH_AXIS_PARENT && node && node->type == LEPTRIS_NODE_TYPE_ATTRIBUTE) {
|
|
764
764
|
LeptrisElement owner = ((LeptrisAttributeNode*)node)->owner;
|
|
765
765
|
XPathNodeSet* result = xpath_nodeset_new();
|
|
766
766
|
if (!result) return result;
|
|
@@ -3651,8 +3651,17 @@ LEPTRIS_API int leptris_xsd_content_valid(
|
|
|
3651
3651
|
XsdCm* model = ct->first_child;
|
|
3652
3652
|
if (!model) return child_count == 0;
|
|
3653
3653
|
|
|
3654
|
-
|
|
3655
|
-
|
|
3654
|
+
int ok = xsd_content_valid(s, model, s->target_ns, child_names,
|
|
3655
|
+
child_ns, child_count);
|
|
3656
|
+
/* #1894: -2 = the model crosses the automaton size cap — surface
|
|
3657
|
+
* the loud structured row and keep the public contract's -1 for
|
|
3658
|
+
* "not evaluable". */
|
|
3659
|
+
if (ok == -2) {
|
|
3660
|
+
xsd_set_error(s, "content model exceeds the automaton size "
|
|
3661
|
+
"cap (pathological occurrence product)");
|
|
3662
|
+
return -1;
|
|
3663
|
+
}
|
|
3664
|
+
return ok;
|
|
3656
3665
|
}
|
|
3657
3666
|
|
|
3658
3667
|
LEPTRIS_API size_t leptris_xsd_declaration_count(LeptrisXsdSchema schema) {
|
|
@@ -29,12 +29,34 @@ typedef struct {
|
|
|
29
29
|
int start, accept;
|
|
30
30
|
struct leptris_xsd_schema* s; /* group-ref resolution */
|
|
31
31
|
int depth; /* cyclic-group guard */
|
|
32
|
+
int overflow; /* #1894: crossed XSD_CM_NFA_MAX — abort the build */
|
|
32
33
|
} CmNfa;
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
/* leptris#1894: a counted particle multiplies the expanded NFA (finite
|
|
36
|
+
* maxOccurs copies the subtree per copy), so nested large bounds grow
|
|
37
|
+
* the automaton exponentially and a huge finite bound walks the copy
|
|
38
|
+
* loop until the process dies (jetsam/OOM, no diagnostic). Crossing
|
|
39
|
+
* this bound aborts the build; xsd_content_valid reports -2 and the
|
|
40
|
+
* callers surface a loud structured row. Generous: legitimate suite
|
|
41
|
+
* content models stay orders of magnitude below it. */
|
|
42
|
+
#define XSD_CM_NFA_MAX 1000000
|
|
43
|
+
|
|
44
|
+
static int nfa_state(CmNfa* n) {
|
|
45
|
+
if (n->overflow) return 0;
|
|
46
|
+
if (n->state_count >= XSD_CM_NFA_MAX) {
|
|
47
|
+
n->overflow = 1;
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
return n->state_count++;
|
|
51
|
+
}
|
|
35
52
|
|
|
36
53
|
static void nfa_trans(CmNfa* n, int from, int symbol, XsdCm* particle,
|
|
37
54
|
int to) {
|
|
55
|
+
if (n->overflow) return;
|
|
56
|
+
if (n->count >= XSD_CM_NFA_MAX) {
|
|
57
|
+
n->overflow = 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
38
60
|
if (n->count == n->cap) {
|
|
39
61
|
size_t cap = n->cap ? n->cap * 2 : 16;
|
|
40
62
|
CmTrans* grown = (CmTrans*)realloc(n->trans, cap * sizeof(*grown));
|
|
@@ -125,7 +147,9 @@ static void cm_build(CmNfa* n, XsdCm* node, int from, int to) {
|
|
|
125
147
|
/* occurrence bounds: min copies, then (max-min) optionals, or an
|
|
126
148
|
* epsilon self-loop region for unbounded. */
|
|
127
149
|
static void cm_build_occurrence(CmNfa* n, XsdCm* node, int from, int to) {
|
|
150
|
+
if (n->overflow) return;
|
|
128
151
|
for (int i = 0; i < node->min; i++) {
|
|
152
|
+
if (n->overflow) return;
|
|
129
153
|
int mid = nfa_state(n);
|
|
130
154
|
cm_build(n, node, from, mid);
|
|
131
155
|
from = mid;
|
|
@@ -138,6 +162,7 @@ static void cm_build_occurrence(CmNfa* n, XsdCm* node, int from, int to) {
|
|
|
138
162
|
return;
|
|
139
163
|
}
|
|
140
164
|
for (int i = node->min; i < node->max; i++) {
|
|
165
|
+
if (n->overflow) return;
|
|
141
166
|
nfa_trans(n, from, -1, NULL, to);
|
|
142
167
|
int mid = nfa_state(n);
|
|
143
168
|
cm_build(n, node, from, mid);
|
|
@@ -146,6 +171,62 @@ static void cm_build_occurrence(CmNfa* n, XsdCm* node, int from, int to) {
|
|
|
146
171
|
nfa_trans(n, from, -1, NULL, to);
|
|
147
172
|
}
|
|
148
173
|
|
|
174
|
+
/* ---- #1894 analytic product bound (pre-build rejection) ----------- */
|
|
175
|
+
|
|
176
|
+
/* Saturating upper bound on the states+transitions one subtree
|
|
177
|
+
* expands, honoring the same occurrence lowering cm_build_occurrence
|
|
178
|
+
* performs: finite max copies the subtree max times; unbounded lowers
|
|
179
|
+
* to ONE loop region (min + 1 copies). Groups follow like cm_build
|
|
180
|
+
* (depth-capped; unresolved/cyclic refs count as 1 — the expansion
|
|
181
|
+
* cap remains the backstop for anything the walk cannot see). Returns
|
|
182
|
+
* nonzero when the bound crosses XSD_CM_NFA_MAX. */
|
|
183
|
+
static int cm_bound_over(struct leptris_xsd_schema* s,
|
|
184
|
+
const XsdCm* node, size_t* bound, int depth) {
|
|
185
|
+
if (!node || depth > 64) return 0;
|
|
186
|
+
size_t sub;
|
|
187
|
+
switch (node->kind) {
|
|
188
|
+
case XSD_CM_ELEMENT:
|
|
189
|
+
case XSD_CM_ANY:
|
|
190
|
+
sub = 1;
|
|
191
|
+
break;
|
|
192
|
+
case XSD_CM_GROUP_REF: {
|
|
193
|
+
XsdGroupDef* g = s ? xsd_find_group(s, node->name) : NULL;
|
|
194
|
+
if (!g || !g->model ||
|
|
195
|
+
cm_bound_over(s, g->model, &sub, depth + 1))
|
|
196
|
+
sub = 1;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case XSD_CM_SEQ:
|
|
200
|
+
case XSD_CM_ALL:
|
|
201
|
+
case XSD_CM_CHOICE: {
|
|
202
|
+
sub = 0;
|
|
203
|
+
for (const XsdCm* c = node->first_child; c; c = c->next) {
|
|
204
|
+
size_t cb = 0;
|
|
205
|
+
if (cm_bound_over(s, c, &cb, depth + 1)) return 1;
|
|
206
|
+
if (sub > XSD_CM_NFA_MAX) return 1;
|
|
207
|
+
sub += cb;
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
default:
|
|
212
|
+
sub = 1;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
/* occurrence multiplier: copies of the subtree */
|
|
216
|
+
size_t copies;
|
|
217
|
+
if (node->max < 0)
|
|
218
|
+
copies = (size_t)(node->min > 0 ? node->min : 0) + 1;
|
|
219
|
+
else
|
|
220
|
+
copies = (size_t)(node->max > 0 ? node->max : 0);
|
|
221
|
+
if (copies == 0) {
|
|
222
|
+
*bound = 0;
|
|
223
|
+
return 0;
|
|
224
|
+
}
|
|
225
|
+
if (sub != 0 && copies > XSD_CM_NFA_MAX / sub) return 1;
|
|
226
|
+
*bound = sub * copies + 1;
|
|
227
|
+
return *bound > XSD_CM_NFA_MAX;
|
|
228
|
+
}
|
|
229
|
+
|
|
149
230
|
/* ---- namespace filter (xs:any/@namespace) ------------------------ */
|
|
150
231
|
|
|
151
232
|
/* XSD 1.1 notQName hit test (moxml#460): ##defined matches a name
|
|
@@ -297,7 +378,19 @@ int xsd_content_valid(struct leptris_xsd_schema* s, XsdCm* model,
|
|
|
297
378
|
n.s = s;
|
|
298
379
|
n.start = nfa_state(&n);
|
|
299
380
|
n.accept = nfa_state(&n);
|
|
381
|
+
/* #1894: bound the expansion analytically BEFORE building — a
|
|
382
|
+
* pathological occurrence product (nested finite maxOccurs)
|
|
383
|
+
* rejects in microseconds instead of growing the automaton until
|
|
384
|
+
* the process dies. */
|
|
385
|
+
{
|
|
386
|
+
size_t bound = 0;
|
|
387
|
+
if (cm_bound_over(s, model, &bound, 0)) return -2;
|
|
388
|
+
}
|
|
300
389
|
cm_build_occurrence(&n, model, n.start, n.accept);
|
|
390
|
+
if (n.overflow) {
|
|
391
|
+
free(n.trans);
|
|
392
|
+
return -2;
|
|
393
|
+
}
|
|
301
394
|
|
|
302
395
|
StateSet live;
|
|
303
396
|
memset(&live, 0, sizeof(live));
|
|
@@ -391,6 +391,19 @@ static void validate_children(struct xsd_validator* v,
|
|
|
391
391
|
* min == 0. names/uris stay NULL (never dereferenced at n==0). */
|
|
392
392
|
int ok = xsd_content_valid(s, model, xsd_target_ns(s), names, uris,
|
|
393
393
|
n);
|
|
394
|
+
if (ok == -2) {
|
|
395
|
+
/* #1894: pathological occurrence product — the automaton
|
|
396
|
+
* exceeds the compile-time size cap. Loud, not a hang. */
|
|
397
|
+
const char* l2 = NULL;
|
|
398
|
+
leptris_element_expanded_name(elem, &l2, NULL, NULL);
|
|
399
|
+
verrf_atk(v, elem, "content-model", l2 ? l2 : "", "element",
|
|
400
|
+
l2 ? l2 : "",
|
|
401
|
+
"content model exceeds the automaton size cap "
|
|
402
|
+
"(pathological occurrence product)");
|
|
403
|
+
free(names);
|
|
404
|
+
free(uris);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
394
407
|
if (ok) {
|
|
395
408
|
free(names);
|
|
396
409
|
free(uris);
|
|
@@ -974,3 +974,35 @@ TEST(ParseErrorPosition, GenericFailuresStayGeneric) {
|
|
|
974
974
|
ASSERT_NE(err, nullptr);
|
|
975
975
|
EXPECT_NE(std::strstr(err, "malformed input"), nullptr) << err;
|
|
976
976
|
}
|
|
977
|
+
|
|
978
|
+
/* leptris#1901: linux-only round-trip attribute loss — sz/szCs w:val
|
|
979
|
+
* runs vanish between parse and serialize on x86_64-linux (uniword
|
|
980
|
+
* matrix: darwin green, linux red, same seed + gem versions). Pin the
|
|
981
|
+
* OOXML shape so the ubuntu lane arbitrates the platform split. */
|
|
982
|
+
TEST(RoundTrip, OoxmlRunPropertiesKeepValAttributes) {
|
|
983
|
+
const char xml[] =
|
|
984
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
|
985
|
+
"<w:document xmlns:w=\"http://schemas.openxmlformats.org/"
|
|
986
|
+
"wordprocessingml/2006/main\"><w:body><w:p><w:pPr><w:rPr>"
|
|
987
|
+
"<w:sz w:val=\"24\"/><w:szCs w:val=\"24\"/></w:rPr></w:pPr>"
|
|
988
|
+
"<w:r><w:rPr><w:sz w:val=\"24\"/><w:szCs w:val=\"24\"/>"
|
|
989
|
+
"</w:rPr><w:t xml:space=\"preserve\">hi there</w:t></w:r>"
|
|
990
|
+
"</w:p></w:body></w:document>";
|
|
991
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
992
|
+
LeptrisDocument doc =
|
|
993
|
+
leptris_parse_string(xml, std::strlen(xml), &st);
|
|
994
|
+
ASSERT_EQ(st, LEPTRIS_OK);
|
|
995
|
+
ASSERT_NE(doc, nullptr);
|
|
996
|
+
char* out = leptris_document_serialize(doc, NULL);
|
|
997
|
+
ASSERT_NE(out, nullptr);
|
|
998
|
+
/* all four w:val attributes survive the round trip */
|
|
999
|
+
int val_count = 0;
|
|
1000
|
+
for (const char* p = out; (p = std::strstr(p, "w:val=\"24\"")) != NULL;
|
|
1001
|
+
p++)
|
|
1002
|
+
val_count++;
|
|
1003
|
+
EXPECT_EQ(val_count, 4) << out;
|
|
1004
|
+
EXPECT_NE(std::strstr(out, "<w:sz w:val=\"24\"/>"), nullptr);
|
|
1005
|
+
EXPECT_NE(std::strstr(out, "<w:szCs w:val=\"24\"/>"), nullptr);
|
|
1006
|
+
leptris_free_string(out);
|
|
1007
|
+
leptris_document_free(doc);
|
|
1008
|
+
}
|
|
@@ -3624,3 +3624,59 @@ TEST(XsdValidate, QNameNotationIgnoreLengthFacets) {
|
|
|
3624
3624
|
EXPECT_EQ(validate_doc(ul, "<test a='x y'/>"), 1);
|
|
3625
3625
|
EXPECT_EQ(validate_doc(ul, "<test a='x'/>"), 0);
|
|
3626
3626
|
}
|
|
3627
|
+
|
|
3628
|
+
/* leptris#1894: pathological occurrence products. A counted particle
|
|
3629
|
+
* multiplies the expanded NFA (finite maxOccurs copies the subtree per
|
|
3630
|
+
* copy), so nested large bounds grow the automaton exponentially and a
|
|
3631
|
+
* huge finite bound walks the copy loop until the process dies. The
|
|
3632
|
+
* compile-time size guard fails LOUDLY — a structured report row and a
|
|
3633
|
+
* -1 (not evaluable) from the public face — instead of consuming the
|
|
3634
|
+
* machine. */
|
|
3635
|
+
TEST(XsdContent, PathologicalProductFailsLoudlyNotOom) {
|
|
3636
|
+
std::string xsd =
|
|
3637
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
|
|
3638
|
+
"<xs:element name=\"r\"><xs:complexType><xs:sequence"
|
|
3639
|
+
" minOccurs=\"0\" maxOccurs=\"2000\"><xs:element name=\"e\""
|
|
3640
|
+
" minOccurs=\"0\" maxOccurs=\"2000\"/></xs:sequence>"
|
|
3641
|
+
"</xs:complexType></xs:element></xs:schema>";
|
|
3642
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3643
|
+
LeptrisXsdSchema s =
|
|
3644
|
+
leptris_xsd_compile(xsd.data(), xsd.size(), &st);
|
|
3645
|
+
ASSERT_EQ(st, LEPTRIS_OK);
|
|
3646
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3647
|
+
/* 2000 x 2000 = 4e6 expanded copies — over the cap. Zero children
|
|
3648
|
+
* keep the simulation cheap; the BUILD is what the guard bounds. */
|
|
3649
|
+
EXPECT_EQ(leptris_xsd_content_valid(s, "r", NULL, NULL, 0), -1);
|
|
3650
|
+
/* the loud message rides the schema error face (validator rows
|
|
3651
|
+
* carry it on the instance-validation path instead) */
|
|
3652
|
+
const char* err = leptris_xsd_error(s);
|
|
3653
|
+
ASSERT_NE(err, nullptr);
|
|
3654
|
+
EXPECT_NE(std::string(err).find("size cap"), std::string::npos)
|
|
3655
|
+
<< "error: " << err;
|
|
3656
|
+
leptris_xsd_free(s);
|
|
3657
|
+
}
|
|
3658
|
+
|
|
3659
|
+
TEST(XsdContent, Issue1894ReproStaysUnderCapAndCorrect) {
|
|
3660
|
+
/* The issue's exact shape — seq maxOccurs=100 x element
|
|
3661
|
+
* unbounded — lowers to a loop region (not copies) and must stay
|
|
3662
|
+
* far under the cap with normal answers. */
|
|
3663
|
+
const char xsd[] =
|
|
3664
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
|
|
3665
|
+
"<xs:element name=\"r\"><xs:complexType><xs:sequence"
|
|
3666
|
+
" maxOccurs=\"100\"><xs:element name=\"e\""
|
|
3667
|
+
" maxOccurs=\"unbounded\"/></xs:sequence></xs:complexType>"
|
|
3668
|
+
"</xs:element></xs:schema>";
|
|
3669
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3670
|
+
LeptrisXsdSchema s =
|
|
3671
|
+
leptris_xsd_compile(xsd, strlen(xsd), &st);
|
|
3672
|
+
ASSERT_EQ(st, LEPTRIS_OK);
|
|
3673
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3674
|
+
const char* e[] = {"e"};
|
|
3675
|
+
EXPECT_EQ(leptris_xsd_content_valid(s, "r", e, NULL, 1), 1);
|
|
3676
|
+
/* minOccurs defaults to 1 on the inner element: empty violates */
|
|
3677
|
+
EXPECT_EQ(leptris_xsd_content_valid(s, "r", NULL, NULL, 0), 0);
|
|
3678
|
+
const char* x[] = {"x"};
|
|
3679
|
+
EXPECT_EQ(leptris_xsd_content_valid(s, "r", x, NULL, 1), 0);
|
|
3680
|
+
EXPECT_EQ(leptris_xsd_error_count(s), 0u);
|
|
3681
|
+
leptris_xsd_free(s);
|
|
3682
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
|
|
3
3
|
"name": "leptris",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.390",
|
|
5
5
|
"description": "High-performance XML parser and XPath 1.0 engine in C (libleptris)",
|
|
6
6
|
"homepage": "https://github.com/leptris/leptris",
|
|
7
7
|
"license": "MIT",
|