yeptris 0.6.31.2-arm-linux-eabihf → 0.6.33.1-arm-linux-eabihf

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: 94c34bc92701bb3906ae0f223c8b0fed12547cce0cee8409d18a9aa909acc439
4
- data.tar.gz: 5fecb214844b15ff11b1eb328c1dfeb787197b95664064653fd5ca5f15767163
3
+ metadata.gz: 1d260e3ce22ef10161a630f46579c9b12f02698319e2ed9b95a986d5faa85927
4
+ data.tar.gz: ecfadcb84f6475cdf83e14ee41d1396e2b2a704f75cb524b66dee032c4396ed1
5
5
  SHA512:
6
- metadata.gz: c0af127b4140cd6c59abe4de51dda33d32bf60ec929e50c456b17f876ab1fe648db6253bca117f479541fd4c5303e23886d38ed934f509fb62e151102cba0a5d
7
- data.tar.gz: 21bcbff5971b2f1df8e992377e65a5854a01d3f10b30c88600a69f60d8f537ec2ac92f84c07ab0954770d261e744dc955e9e0faed9ea08dc07145cffe49e92ae
6
+ metadata.gz: 1137d08cdea4a4bd1272e98ae1d8906a21cc918e13d23cf61015734d3581bf488154f8f2762230be2a45d1dd6766de72af687b8d987b128303864adf22e95890
7
+ data.tar.gz: cfff652c21cd403c3622dc2f73102621182b1d9ab356796735e4f4bfb60498c4a9e3aee2c67f2e457eb336f293a93b90ee0f6a7ee6e6bf6a0c5afe5bc82c2df8
Binary file
data/lib/yeptris/node.rb CHANGED
@@ -50,7 +50,7 @@ class Yeptris::Node
50
50
 
51
51
  # Scalar content / alias name (UTF-8 String), nil for collections.
52
52
  def value
53
- len = ::FFI::MemoryPointer.new(:size_t)
53
+ len = len_buffer
54
54
  ptr = alive { Yeptris::FFI.yeptris_node_value(@c_ptr, len) }
55
55
  return nil if ptr.null?
56
56
 
@@ -69,9 +69,18 @@ class Yeptris::Node
69
69
  STYLES[alive { Yeptris::FFI.yeptris_node_style(@c_ptr) }]
70
70
  end
71
71
 
72
+ # The out-length receiver: ONE buffer per thread, reused. A fresh
73
+ # FFI::MemoryPointer per accessor call was an allocation storm that
74
+ # stalled the Windows heap under the #182 churn loop (the #504
75
+ # family — the hang's stack sits in FFI::MemoryPointer#initialize,
76
+ # node.rb anchor/tag reads inside Integer#times with GC.start).
77
+ def len_buffer
78
+ Thread.current[:yeptris_len_buf] ||= ::FFI::MemoryPointer.new(:size_t)
79
+ end
80
+
72
81
  # Explicit tag URI when present, else nil.
73
82
  def tag
74
- len = ::FFI::MemoryPointer.new(:size_t)
83
+ len = len_buffer
75
84
  ptr = alive { Yeptris::FFI.yeptris_node_tag(@c_ptr, len) }
76
85
  return nil if ptr.null?
77
86
 
@@ -79,7 +88,7 @@ class Yeptris::Node
79
88
  end
80
89
 
81
90
  def anchor
82
- len = ::FFI::MemoryPointer.new(:size_t)
91
+ len = len_buffer
83
92
  ptr = alive { Yeptris::FFI.yeptris_node_anchor(@c_ptr, len) }
84
93
  return nil if ptr.null?
85
94
 
@@ -216,7 +216,7 @@ module Yeptris
216
216
  # explicit !!str tag (single-quoted) so it does not
217
217
  # re-load as a merge
218
218
  key_node = @tree.new_scalar("<<", :single_quoted)
219
- key_node.set_tag("!!str")
219
+ key_node.set_tag("tag:yaml.org,2002:str")
220
220
  m.map_add_node(key_node, visit(v))
221
221
  else
222
222
  m.map_add(key_text(k), visit(v))
data/lib/yeptris/yaml.rb CHANGED
@@ -364,7 +364,7 @@ module Yeptris
364
364
  # stdlib yaml_tree: a literal chevron key carries the
365
365
  # explicit !!str tag so it does not re-load as a merge
366
366
  key_node = doc.new_scalar("<<", :single_quoted)
367
- key_node.set_tag("!!str")
367
+ key_node.set_tag("tag:yaml.org,2002:str")
368
368
  m.map_add_node(key_node, build(doc, v, seen))
369
369
  else
370
370
  m.map_add(key_text(k), build(doc, v, seen))
data/lib/yeptris.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Yeptris
4
4
  # The gem's version lives in the parent namespace's file — the last
5
5
  # internal require (yeptris/version) retired with it.
6
- VERSION = "0.6.31.2".freeze
6
+ VERSION = "0.6.33.1".freeze
7
7
 
8
8
  # Informational notices are OPT-IN (yeptris-ruby#217): consumers
9
9
  # embed yeptris inside CLIs that assert clean stderr, and a
data/libyeptris.so CHANGED
Binary file
@@ -3,7 +3,7 @@
3
3
  cmake_minimum_required(VERSION 3.20)
4
4
 
5
5
  project(yeptris
6
- VERSION 0.6.31
6
+ VERSION 0.6.33
7
7
  DESCRIPTION "Ultra-fast YAML 1.2 parser, emitter and streamer in C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -98,15 +98,27 @@ if(YEPTRIS_ENABLE_UBSAN)
98
98
  message(STATUS "UndefinedBehaviorSanitizer: ENABLED (fatal)")
99
99
  endif()
100
100
 
101
- # libFuzzer implies ASAN (libleptris TODO 40 pattern).
101
+ # libFuzzer implies ASAN+UBSan (the teptris fuzz.yml pattern: the
102
+ # memory-safety contracts ride the SAME binary as the fuzzer, so every
103
+ # nightly round reports UB at the crash site instead of libFuzzer's
104
+ # "combine with AddressSanitizer" note).
102
105
  if(YEPTRIS_ENABLE_FUZZING)
103
106
  # instrument everything, but link the fuzzer MAIN only into the
104
107
  # harnesses: a global -fsanitize=fuzzer link option demands
105
108
  # LLVMFuzzerTestOneInput from every executable (the CLI and the
106
109
  # test binaries died on it once CXX also pinned to clang++)
107
- add_compile_options(-fsanitize=fuzzer-no-link,address -fno-omit-frame-pointer -g)
108
- add_link_options(-fsanitize=address)
109
- message(STATUS "libFuzzer: ENABLED (implies ASAN)")
110
+ if(APPLE)
111
+ # Apple ld64 cannot link UBSan'd static archives
112
+ # ("invalid r_symbolnum"): ASan-only locally
113
+ add_compile_options(-fsanitize=fuzzer-no-link,address -fno-omit-frame-pointer -g)
114
+ add_link_options(-fsanitize=address)
115
+ message(STATUS "libFuzzer: ENABLED (implies ASAN; UBSan needs linux ld)")
116
+ else()
117
+ add_compile_options(-fsanitize=fuzzer-no-link,address,undefined
118
+ -fno-sanitize-recover=undefined -fno-omit-frame-pointer -g)
119
+ add_link_options(-fsanitize=address,undefined)
120
+ message(STATUS "libFuzzer: ENABLED (implies ASAN+UBSan)")
121
+ endif()
110
122
  endif()
111
123
 
112
124
  # -------------------------------------------------------------------- LTO --
@@ -392,6 +392,27 @@ int yep_dom_on_event(void* ctx, const yep_event* ev) {
392
392
  if (d->depth == 0) {
393
393
  return -1;
394
394
  }
395
+ if (ev->type == YEP_EV_MAP_END && d->map_pending_key[d->depth - 1]) {
396
+ /* an odd child reached the mapping: the unpaired node —
397
+ * possibly an ANCHORED one — used to be dropped here, its
398
+ * anchor lost, and a later alias then emitted a dangling
399
+ * reference the re-parse rejected (the nightly's round
400
+ * 102). Pair it with a null: "k:" with nothing is a null
401
+ * value in every other position. */
402
+ yep_event nv;
403
+ memset(&nv, 0, sizeof(nv));
404
+ nv.type = YEP_EV_SCALAR;
405
+ nv.style = YEP_STYLE_PLAIN;
406
+ nv.implicit = 1;
407
+ uint32_t nid = dom_new_node(d, &nv, YEP_DOM_SCALAR);
408
+ if (nid == UINT32_MAX) {
409
+ return -1;
410
+ }
411
+ uint32_t top = d->stack[d->depth - 1];
412
+ dom_link(d, top, d->pending_key_id[d->depth - 1]);
413
+ dom_link(d, top, nid);
414
+ d->map_pending_key[d->depth - 1] = 0;
415
+ }
395
416
  d->depth--;
396
417
  return 0;
397
418
 
@@ -729,6 +750,7 @@ static int jb_value(jbuilder* b) {
729
750
  return 0;
730
751
  }
731
752
  for (;;) {
753
+ size_t member_start = b->i;
732
754
  int rc = jb_value(b);
733
755
  if (rc != 0) {
734
756
  return rc;
@@ -738,6 +760,14 @@ static int jb_value(jbuilder* b) {
738
760
  /* a value must be followed by , or } — the map's key
739
761
  * slot is pending until the ':' value completes */
740
762
  if (b->i < b->len && b->p[b->i] == ':' && d->map_pending_key[d->depth - 1] != 0) {
763
+ /* libyaml's simple-key law rides the JSON-class
764
+ * route too: a key whose colon distance crosses
765
+ * 1024 characters defers to the engine's clean
766
+ * error (run 38143486175) */
767
+ if (b->i - member_start > 1024 &&
768
+ yep_simple_key_chars(b->p + member_start, b->i - member_start) > 1024) {
769
+ return -2;
770
+ }
741
771
  b->i++;
742
772
  rc = jb_value(b);
743
773
  if (rc != 0) {
@@ -820,8 +850,11 @@ int dom_on_flow_build(void* ctx, const char* p, size_t open, size_t len, uint32_
820
850
  yep_json_walk w;
821
851
  yep_json_tok t;
822
852
  yep_json_walk_init(&w, p, len, open, max_depth);
823
- w.strict = d->flow_strict; /* the strict-JSON route rides the same
824
- fused walk (TODO.restructure/81) */
853
+ w.strict = 1; /* the same byte-for-byte JSON gate as the engine's
854
+ * pass 1: a lenient walk split number/literal keys
855
+ * across the fast/slow paths (whole {9->1} vs chunked
856
+ * {"9:1"->null}); flow_strict keeps owning the TAG
857
+ * route only (TODO.restructure/81) */
825
858
  for (;;) {
826
859
  yep_jw_status st = yep_json_walk_next(&w, &t);
827
860
  if (st == YEP_JW_REJECT) {
@@ -976,6 +1009,23 @@ int dom_from_tape(yep_dom* d, const yeptris_json_tape* t) {
976
1009
  if (d->depth == 0) {
977
1010
  return -1;
978
1011
  }
1012
+ if (d->nodes[d->stack[d->depth - 1]].kind == YEP_DOM_MAPPING &&
1013
+ d->map_pending_key[d->depth - 1]) {
1014
+ /* an odd child reached the mapping (see the event-path
1015
+ * MAP_END): pair it with a null instead of dropping it */
1016
+ yep_event nv;
1017
+ memset(&nv, 0, sizeof(nv));
1018
+ nv.type = YEP_EV_SCALAR;
1019
+ nv.style = YEP_STYLE_PLAIN;
1020
+ nv.implicit = 1;
1021
+ uint32_t nid = dom_new_node(d, &nv, YEP_DOM_SCALAR);
1022
+ if (nid == UINT32_MAX) {
1023
+ return -1;
1024
+ }
1025
+ dom_link(d, d->stack[d->depth - 1], d->pending_key_id[d->depth - 1]);
1026
+ dom_link(d, d->stack[d->depth - 1], nid);
1027
+ d->map_pending_key[d->depth - 1] = 0;
1028
+ }
979
1029
  d->depth--;
980
1030
  break;
981
1031
  case YEP_T_NULL: