leptris 1.9.398.0-arm-linux → 1.9.400.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1dd34459853a189e9e6de557438320ca4e4cdb3962866cb1e136d52656d28ebc
4
- data.tar.gz: 7cb6b2d19f346d36f0e94b2aae7e2fbd429865fb27f5b1ce753ca9d545fa8216
3
+ metadata.gz: add6b5b23fd754aa96b9f000135bda072a60dae134983c6b0ffc3a3338e84d06
4
+ data.tar.gz: 3eb82ecc509b6ce7371c7653e544498ffd16733eb16a55be7e1fbb7e2a92686d
5
5
  SHA512:
6
- metadata.gz: 64fe432cfa7815bc74d77de6c46cff709271a1d11372daa551af133ed838f1a5cf94aefcd88711238230301eae86444bdb60601a4a7874715db74f6f83e4b654
7
- data.tar.gz: 6c98902cf61cbf36a72ec93159b8e8545e5bcfdcef8aa35314ead57060d45d084b6c2b01bf7c7f48ac9b04c9428355a352524a439fab396149da8e5dd6274215
6
+ metadata.gz: d33e24719cbd53016641ee3d29a119e2dbb0890697eacc4a4435297f0eccbed7637e615625e8c6ce53451526cd4b339d6be3b7aee28ed7cff982732b590d1279
7
+ data.tar.gz: f250190b495e01fee4a005de5678851a920443197cb84adfbc0e48c2f2a20e5a8e82fec78fb7382f9d2a60fad88a4370ce1ce50ce3d22c716391b5da67ce6487
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.398"
11
+ LIBLEPTRIS_VERSION = "1.9.400"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.398.0"
4
+ VERSION = "1.9.400.0"
5
5
  end
data/lib/libleptris.so CHANGED
Binary file
data/vendor-src/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Sources vendored in this gem (recompile rights; the ruby
2
2
  variant builds them at install via extconf.rb):
3
3
 
4
- - libleptris v1.9.398
4
+ - libleptris v1.9.400
5
5
  - utf8proc v2.11.0
6
6
 
7
7
  Rebuild by hand:
@@ -1,5 +1,42 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.9.400] - 2026-11-01
4
+
5
+ ### Fixed
6
+
7
+ - **A restriction's inline anonymous base drives validation
8
+ (leptris#1936 stG/stH, PR #1943).** An `xs:restriction` whose
9
+ base is an inline anonymous `<xs:simpleType>` — the W3C suite's
10
+ stG/stH style — never captured that base: values were
11
+ facet-checked with nothing underneath, so `length` counted
12
+ characters of the whole lexical instead of list items. The base
13
+ now rides the capture (`base_def`, mirroring `item_def`/
14
+ `member_defs`), the value passes through the base's own
15
+ derivation before the restriction's facets, and the list-chain
16
+ detector descends the anonymous path. RED-first spec; the
17
+ xmllint-arbiter harness agrees on all 8 collected
18
+ schema/instance pairs. (xsd)
19
+
20
+
21
+
22
+ ## [1.9.399] - 2026-10-31
23
+
24
+ ### Fixed
25
+
26
+ - **`\\d` matches the Unicode-3.1 legacy digits (leptris#1936,
27
+ PR #1940).** XSD 1.0 Part 2 cites Unicode 3.1, where
28
+ U+1369–U+1371 (Ethiopic digits one-nine) were Nd — Unicode 4.0.1
29
+ demoted them to No, so the utf8proc-backed Nd mask missed them
30
+ and the suite's reS38 (`\\d` vs `&#x1371;`) / reT51 (`\\D`) rows
31
+ failed. The legacy-Nd set now joins the class as a pure-codepoint
32
+ range, outside the utf8proc guard so every build (windows
33
+ included) answers it; `\\D` inherits the exclusion through the
34
+ complement's negation. RED-first spec
35
+ (`XsdDatatypes.DigitClassPinsLegacyNd`), and the shared-fixture
36
+ collision behind an arm-lane flake got unique names.
37
+
38
+
39
+
3
40
  ## [1.9.398] - 2026-10-31
4
41
 
5
42
  ### Fixed
@@ -169,3 +169,19 @@ calculates the next version, and updates three files:
169
169
  - `CHANGELOG.md` (version header)
170
170
 
171
171
  The bump-version.sh script handles all three in one shot.
172
+
173
+ ### Runtime coverage law: publish ALL runtimes every release
174
+
175
+ An engine release is NOT done when the GitHub Release publishes — it is
176
+ done when every runtime package riding it is published and VERIFIED on
177
+ its registry, same day: **ruby** (rubygems, leptris-ruby: bump Rakefile
178
+ `LIBLEPTRIS_VERSION` + `lib/leptris/version.rb`; merge = publish), **py**
179
+ (PyPI, leptris-py: bump `libleptris-version.txt` + `pyproject.toml` +
180
+ `leptris/__init__.py`; merge = publish), **rs** (crates.io, leptris-rs:
181
+ conventional commits -> merge release-plz's release PR = publish), **ts**
182
+ (npm package `leptris`, leptris-ts: bump pin + `package.json`; the
183
+ `v<pkg>` tag push publishes). Verify on the registry itself — a merged
184
+ PR with a stuck workflow is not a release (2026-10-29: ruby sat two
185
+ engine releases behind with the pin already advanced; py seven behind;
186
+ rs's release workflow had never succeeded — missing `id-token: write`;
187
+ ts 0.1.24 never tagged).
@@ -3,7 +3,7 @@
3
3
  cmake_minimum_required(VERSION 3.20)
4
4
 
5
5
  project(leptris
6
- VERSION 1.9.398
6
+ VERSION 1.9.400
7
7
  DESCRIPTION "Fast XML parser and XPath evaluator in pure C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -1172,6 +1172,53 @@ No runtime dependencies when built without utf8proc/iconv.
1172
1172
  |libFuzzer for 5 minutes; report any crashes.
1173
1173
  |===
1174
1174
 
1175
+ == Releasing and the runtime packages
1176
+
1177
+ The engine releases via the automated workflow
1178
+ (`gh workflow run release.yml -f next_version=patch` — the workflow
1179
+ bumps the version, opens the release PR, and tags + publishes the
1180
+ GitHub Release when it merges). Never tag or release by hand.
1181
+
1182
+ **Every engine release ships ALL runtime packages the same day** —
1183
+ an engine release is not done until each binding that rides it is
1184
+ published and verified on its registry:
1185
+
1186
+ [cols="1,2,3",options="header"]
1187
+ |===
1188
+ |Runtime |Registry |Ride
1189
+
1190
+ |Ruby
1191
+ |rubygems (`leptris`, `{engine-semver}.{binding-patch}`)
1192
+ |bump `Rakefile` `LIBLEPTRIS_VERSION` + `lib/leptris/version.rb` in
1193
+ link:https://github.com/leptris/leptris-ruby[leptris-ruby]; merging
1194
+ the bump PR is the release decision (auto-publish).
1195
+
1196
+ |Python
1197
+ |PyPI (`leptris`)
1198
+ |bump `libleptris-version.txt` + `pyproject.toml` +
1199
+ `leptris/__init__.py` in
1200
+ link:https://github.com/leptris/leptris-py[leptris-py]; merging the
1201
+ bump PR publishes via trusted publishing.
1202
+
1203
+ |Rust
1204
+ |crates.io (`leptris`)
1205
+ |conventional commits on
1206
+ link:https://github.com/leptris/leptris-rs[leptris-rs] main; the
1207
+ release-plz PR carries the version bump, and merging IT publishes
1208
+ (crates.io trusted publishing).
1209
+
1210
+ |TypeScript / WASM
1211
+ |npm (`leptris`)
1212
+ |bump the engine pin + `package.json` version in
1213
+ link:https://github.com/leptris/leptris-ts[leptris-ts]; the
1214
+ tag-gated `v<pkg-version>` push publishes via npm trusted
1215
+ publishing.
1216
+ |===
1217
+
1218
+ Verify each publication on the registry itself (`gem list -r`,
1219
+ `pip index versions`, the crates.io/npm APIs) — a merged PR with a
1220
+ stuck workflow is NOT a release.
1221
+
1175
1222
  == Project layout
1176
1223
 
1177
1224
  [source,text]
@@ -112,6 +112,17 @@ static void cls_add_builtin(RreNode* n, char c) {
112
112
  n->cat_set = 1;
113
113
  n->cat_mask |= 1u << UTF8PROC_CATEGORY_ND;
114
114
  #endif
115
+ /* XSD 1.0 cites Unicode 3.1, where U+1369-1371
116
+ * (Ethiopic digits one-nine) were Nd — Unicode 4.0.1
117
+ * demoted them to No, so modern tables miss them
118
+ * (#1936 reS38/reT51). Pin the legacy-Nd set outside
119
+ * the utf8proc guard: the ranges are pure codepoints
120
+ * and \d must answer them on every build. */
121
+ if (n->uni_n < 4) {
122
+ n->uni_lo[n->uni_n] = 0x1369;
123
+ n->uni_hi[n->uni_n] = 0x1371;
124
+ n->uni_n++;
125
+ }
115
126
  break;
116
127
  case 'w':
117
128
  for (int i = '0'; i <= '9'; i++) cls_add(n, (unsigned char)i);
@@ -428,6 +428,22 @@ static XsdSimple* xsd_capture_simple(LeptrisElement st) {
428
428
  } else if (strcmp(local, "restriction") == 0) {
429
429
  simple->base = xsd_strdup(xsd_local_name(
430
430
  leptris_element_attribute(e, "base")));
431
+ /* #1936 (stG/stH): an inline anonymous BASE rides this
432
+ * capture — without it the restriction's facets apply
433
+ * with no base (length counted characters, list
434
+ * semantics vanished). Mirrors the union member_defs. */
435
+ for (LeptrisNodeRef b = leptris_node_first_child(
436
+ leptris_element_as_node(e));
437
+ b && !simple->base_def;
438
+ b = leptris_node_next_sibling(b)) {
439
+ if (leptris_node_get_type(b) != LEPTRIS_NODE_TYPE_ELEMENT)
440
+ continue;
441
+ LeptrisElement be = (LeptrisElement)b;
442
+ const char* bl = NULL;
443
+ leptris_element_expanded_name(be, &bl, NULL, NULL);
444
+ if (bl && strcmp(bl, "simpleType") == 0)
445
+ simple->base_def = xsd_capture_simple(be);
446
+ }
431
447
  for (LeptrisNodeRef f = leptris_node_first_child(
432
448
  leptris_element_as_node(e));
433
449
  f; f = leptris_node_next_sibling(f)) {
@@ -584,7 +600,13 @@ static int xsd_chain_is_list(struct leptris_xsd_schema* s,
584
600
  int depth = 0;
585
601
  while (t && depth < 32) {
586
602
  if (t->deriv == XSD_SIMPLE_LIST) return 1;
587
- if (!t->base) return 0;
603
+ if (!t->base) {
604
+ /* #1936: an anonymous inline base continues the chain —
605
+ * a restriction of an inline list keeps list semantics
606
+ * (the length family counts items). */
607
+ if (t->base_def) { t = t->base_def; depth++; continue; }
608
+ return 0;
609
+ }
588
610
  if (strncmp(t->base, "xs:", 3) == 0)
589
611
  return strcmp(t->base, "xs:IDREFS") == 0 ||
590
612
  strcmp(t->base, "xs:NMTOKENS") == 0 ||
@@ -651,6 +673,11 @@ static int xsd_deriv_valid(struct leptris_xsd_schema* s,
651
673
  return 1;
652
674
  return 0;
653
675
  }
676
+ /* #1936: the value satisfies the inline base (its own
677
+ * derivation — list item walks, union members — first), then
678
+ * this level's facets. */
679
+ if (t->base_def && !xsd_deriv_valid(s, t->base_def, v, depth + 1))
680
+ return 0;
654
681
  return xsd_simple_valid(t, v, xsd_chain_terminal(s, t), 0);
655
682
  }
656
683
 
@@ -663,6 +690,11 @@ static int xsd_valid_chain(struct leptris_xsd_schema* s,
663
690
  }
664
691
  if (t->deriv != XSD_SIMPLE_RESTRICT)
665
692
  return xsd_deriv_valid(s, t, v, depth);
693
+ /* #1936: the inline anonymous base drives the value first
694
+ * (its own derivation — list item walks, union members),
695
+ * then this restriction's facets. */
696
+ if (t->base_def && !xsd_deriv_valid(s, t->base_def, v, depth + 1))
697
+ return 0;
666
698
  return xsd_simple_valid(t, v, xsd_chain_terminal(s, t),
667
699
  xsd_chain_is_list(s, t));
668
700
  }
@@ -2551,6 +2583,7 @@ static void xsd_free_simple_one(XsdSimple* t) {
2551
2583
  free(t->assertion);
2552
2584
  free(t->item_type);
2553
2585
  xsd_free_simple_one(t->item_def);
2586
+ xsd_free_simple_one(t->base_def);
2554
2587
  for (size_t i = 0; i < t->member_count; i++) free(t->members[i]);
2555
2588
  free(t->members);
2556
2589
  for (size_t i = 0; i < t->member_def_count; i++)
@@ -40,6 +40,7 @@ typedef struct xsd_simple {
40
40
  char* name;
41
41
  char* ns; /* leptris-ruby#440: declaring schema's targetNamespace */
42
42
  char* base;
43
+ struct xsd_simple* base_def; /* RESTRICTION: inline anonymous base */
43
44
  XsdSimpleDeriv deriv;
44
45
  char* item_type; /* LIST: builtin or local type name */
45
46
  struct xsd_simple* item_def; /* LIST: inline anonymous item type */
@@ -390,6 +390,56 @@ TEST(XsdDatatypes, LengthFacetCountsOctetsForHexBinary) {
390
390
  // byte world and character-class SUBTRACTION — the OPC
391
391
  // ST_ContentType shape. A pattern that fails to parse rejects
392
392
  // everything, so media types failed wholesale.
393
+ // leptris#1936 (stG/stH oracle pair): a restriction whose base is
394
+ // an ANONYMOUS inline simpleType must validate the value against
395
+ // that base before its own facets — length on a list-with-length-2
396
+ // counts items, not characters of the whole lexical.
397
+ TEST(XsdDatatypes, RestrictionInlineBaseDrivesFacets) {
398
+ const char xsd[] =
399
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
400
+ "<xs:simpleType name=\"twoInts\"><xs:restriction>"
401
+ "<xs:simpleType><xs:list itemType=\"xs:int\"/></xs:simpleType>"
402
+ "<xs:length value=\"2\"/></xs:restriction></xs:simpleType>"
403
+ "<xs:element name=\"r\" type=\"twoInts\"/></xs:schema>";
404
+ LeptrisStatus st = LEPTRIS_OK;
405
+ LeptrisXsdSchema s = leptris_xsd_compile(xsd, strlen(xsd), &st);
406
+ ASSERT_EQ(st, LEPTRIS_OK);
407
+ ASSERT_NE(s, (LeptrisXsdSchema)0);
408
+ // 2 items: valid per xmllint (the engine used to count chars)
409
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "twoInts", "1 2"), 1);
410
+ // 3 items: over the length facet
411
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "twoInts", "1 2 3"), 0);
412
+ // a member fails the item type
413
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "twoInts", "1 x"), 0);
414
+ leptris_xsd_free(s);
415
+ }
416
+
417
+ // leptris#1936 (reS38/reT51): XSD 1.0 cites Unicode 3.1, where
418
+ // U+1369-1371 (Ethiopic digits one-nine) were Nd — \\d matches
419
+ // &#x1371; and \\D rejects it even though the host tables (4.0.1+)
420
+ // carry them as No.
421
+ TEST(XsdDatatypes, DigitClassPinsLegacyNd) {
422
+ const char xsd[] =
423
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
424
+ "<xs:simpleType name=\"Digs\"><xs:restriction base=\"xs:string\">"
425
+ "<xs:pattern value=\"\\d\"/></xs:restriction></xs:simpleType>"
426
+ "<xs:simpleType name=\"NonDigs\"><xs:restriction base=\"xs:string\">"
427
+ "<xs:pattern value=\"\\D\"/></xs:restriction></xs:simpleType>"
428
+ "</xs:schema>";
429
+ LeptrisStatus st = LEPTRIS_OK;
430
+ LeptrisXsdSchema s = leptris_xsd_compile(xsd, strlen(xsd), &st);
431
+ ASSERT_EQ(st, LEPTRIS_OK);
432
+ ASSERT_NE(s, (LeptrisXsdSchema)0);
433
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "Digs", "\xE1\x8D\xB1"), 1);
434
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "Digs", "\xE1\x8D\xA9"), 1);
435
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "Digs", "5"), 1);
436
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "Digs", "x"), 0);
437
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "NonDigs", "\xE1\x8D\xB1"), 0);
438
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "NonDigs", "5"), 0);
439
+ EXPECT_EQ(leptris_xsd_simple_valid(s, "NonDigs", "x"), 1);
440
+ leptris_xsd_free(s);
441
+ }
442
+
393
443
  TEST(XsdDatatypes, PatternPropertyClassesAndSubtraction) {
394
444
  // The OPC ST_ContentType shape, minus the quoted-string member
395
445
  // (same property-class + subtraction machinery): type/subtype
@@ -3816,7 +3866,7 @@ TEST(XsdCrossNs, SingleDocImportChaseResolves) {
3816
3866
  " xmlns:r=\"urn:r\" xmlns=\"urn:a\" targetNamespace=\"urn:a\""
3817
3867
  " elementFormDefault=\"qualified\">"
3818
3868
  "<xs:import namespace=\"urn:r\""
3819
- " schemaLocation=\"blip_repro_rel.xsd\"/>"
3869
+ " schemaLocation=\"blip_chase_rel.xsd\"/>"
3820
3870
  "<xs:attributeGroup name=\"AG_Blob\">"
3821
3871
  "<xs:attribute ref=\"r:embed\" use=\"optional\"/>"
3822
3872
  "</xs:attributeGroup>"
@@ -3832,8 +3882,8 @@ TEST(XsdCrossNs, SingleDocImportChaseResolves) {
3832
3882
  if (!dir) dir = std::getenv("TEMP"); /* windows runners define TEMP/TMP */
3833
3883
  if (!dir) dir = std::getenv("TMP");
3834
3884
  std::string base = dir ? dir : ".";
3835
- std::string rel_path = base + "/blip_repro_rel.xsd";
3836
- std::string main_path = base + "/blip_repro_main.xsd";
3885
+ std::string rel_path = base + "/blip_chase_rel.xsd";
3886
+ std::string main_path = base + "/blip_chase_main.xsd";
3837
3887
  {
3838
3888
  std::ofstream f(rel_path);
3839
3889
  f << rel;
@@ -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.398",
4
+ "version": "1.9.400",
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",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.398.0
4
+ version: 1.9.400.0
5
5
  platform: arm-linux
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-31 00:00:00.000000000 Z
11
+ date: 2026-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi