syck 1.5.1.1 → 1.6.1

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: 6d9334ff2ab0db4b2d01c78f15fe2b18b8610fa2494157c85f3bbc4c935578cf
4
- data.tar.gz: e68f5b83037746d7b69851736e25d000e142ad33a37e7bf1922080d08c251ee7
3
+ metadata.gz: a6f8be592c6d196af5a6fbf7bdab813819b4303d817f48b2edbc2e3441362382
4
+ data.tar.gz: 309adadd5621cfecdee15f0e36e39b7c1205df6406ab2521cea915b7509196fb
5
5
  SHA512:
6
- metadata.gz: 934bd32bbb33044df770a561daf850b29eb3999cfc0163b2a4cbf4a1e21b4854105249844dd49b1225ac991e6b01b45c1eb67e12c761d37744e498121f130eb2
7
- data.tar.gz: 866376d0f8aee6cf82e2171f0a29367945012ddd5e36c7522cb221281d9c4465ab666bbdbc07c31ff61ca343122b98843ef48225aa354de1aa5c5552da7dbaa0
6
+ metadata.gz: ef57afc974162ffda31cf27709ed5bdad7219f0a181a95a833549d575bfd0edd8fb18967ce380120b477107a643f823294ca83092f17b93a518e49ae59961288
7
+ data.tar.gz: abbdbea1f6eaea32d639b8ea9bcaee50c012c2f362d24d7a49489938eb079eb5c813d437bbf002cdb2ff149d323fd7510db3494075f6bb6c9a0f9884ed87a485
data/README.rdoc CHANGED
@@ -4,9 +4,14 @@
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- A gemified version of Syck from Ruby's stdlib. Syck has been removed from
8
- Ruby's stdlib, and this gem is meant to bridge the gap for people that haven't
9
- updated their YAML yet.
7
+ This Gem is a wrapper around {Syck}[https://github.com/indeyets/syck] (a.k.a.
8
+ Scripters' YAML Cobble-Yourself-a-Parser Kit), used for parsing YAML.
9
+
10
+ Syck has been removed from Ruby's stdlib, and this gem is meant to bridge the
11
+ gap for people that haven't updated their YAML yet.
12
+
13
+ If you are starting a new project, you probably should use
14
+ {Psych}[https://github.com/ruby/psych] instead.
10
15
 
11
16
  == FEATURES/PROBLEMS:
12
17
 
data/ext/syck/implicit.c CHANGED
@@ -11,7 +11,7 @@
11
11
  #include "ruby/ruby.h"
12
12
  #include "syck.h"
13
13
 
14
- #define YYCTYPE char
14
+ #define YYCTYPE unsigned char
15
15
  #define YYCURSOR cursor
16
16
  #define YYMARKER marker
17
17
  #define YYLIMIT limit
data/ext/syck/rubyext.c CHANGED
@@ -13,29 +13,6 @@
13
13
  #include <sys/types.h>
14
14
  #include <time.h>
15
15
 
16
- typedef struct RVALUE {
17
- union {
18
- #if 0
19
- struct {
20
- unsigned long flags; /* always 0 for freed obj */
21
- struct RVALUE *next;
22
- } free;
23
- #endif
24
- struct RBasic basic;
25
- struct RObject object;
26
- /*struct RClass klass;*/
27
- /*struct RFloat flonum;*/
28
- /*struct RString string;*/
29
- struct RArray array;
30
- /*struct RRegexp regexp;*/
31
- /*struct RHash hash;*/
32
- /*struct RData data;*/
33
- /*struct RStruct rstruct;*/
34
- /*struct RBignum bignum;*/
35
- /*struct RFile file;*/
36
- } as;
37
- } RVALUE;
38
-
39
16
  typedef struct {
40
17
  long hash;
41
18
  char *buffer;
@@ -93,6 +70,75 @@ struct emitter_xtra {
93
70
  VALUE port;
94
71
  };
95
72
 
73
+ /*
74
+ * The untyped Data API (Data_Wrap_Struct / Data_Get_Struct) has been
75
+ * removed from current Ruby, so every wrapper here uses the TypedData
76
+ * API and the rb_data_type_t definitions below.
77
+ */
78
+
79
+ static void syck_node_mark(SyckNode *n);
80
+ static void syck_mark_parser(SyckParser *parser);
81
+ void rb_syck_free_parser(SyckParser *p);
82
+ static void syck_mark_emitter(SyckEmitter *emitter);
83
+ void rb_syck_free_emitter(SyckEmitter *e);
84
+
85
+ static const rb_data_type_t syck_parser_type = {
86
+ "syck/parser",
87
+ {
88
+ (void (*)(void *))syck_mark_parser,
89
+ (void (*)(void *))rb_syck_free_parser,
90
+ 0,
91
+ },
92
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
93
+ };
94
+
95
+ static const rb_data_type_t syck_node_type = {
96
+ "syck/node",
97
+ {
98
+ (void (*)(void *))syck_node_mark,
99
+ (void (*)(void *))syck_free_node,
100
+ 0,
101
+ },
102
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
103
+ };
104
+
105
+ /*
106
+ * Nodes owned by the parser must not be freed by the GC. syck_node_type
107
+ * is set as the parent so a single &syck_node_type accepts either kind
108
+ * of node in the accessors below.
109
+ */
110
+ static const rb_data_type_t syck_node_type_nofree = {
111
+ "syck/node",
112
+ {
113
+ (void (*)(void *))syck_node_mark,
114
+ 0,
115
+ 0,
116
+ },
117
+ &syck_node_type, 0, RUBY_TYPED_FREE_IMMEDIATELY,
118
+ };
119
+
120
+ static const rb_data_type_t syck_emitter_type = {
121
+ "syck/emitter",
122
+ {
123
+ (void (*)(void *))syck_mark_emitter,
124
+ (void (*)(void *))rb_syck_free_emitter,
125
+ 0,
126
+ },
127
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
128
+ };
129
+
130
+ /*
131
+ * The taint API (OBJ_TAINT / OBJ_TAINTED) has also been removed from
132
+ * current Ruby, while older supported versions still provide it; shim
133
+ * it to a no-op where Ruby no longer defines it.
134
+ */
135
+ #ifndef OBJ_TAINT
136
+ #define OBJ_TAINT(obj) ((void)(obj))
137
+ #endif
138
+ #ifndef OBJ_TAINTED
139
+ #define OBJ_TAINTED(obj) (0)
140
+ #endif
141
+
96
142
  /*
97
143
  * Convert YAML to bytecode
98
144
  */
@@ -636,6 +682,99 @@ yaml_org_handler( SyckNode *n, VALUE *ref )
636
682
  }
637
683
 
638
684
  static void syck_node_mark( SyckNode *n );
685
+ static VALUE id_hash_new(void);
686
+
687
+ /*
688
+ * Rewrite every reference to `from` inside `obj` so it points at `to`.
689
+ *
690
+ * A self-referential anchor (`--- &a\n- *a\n`) is aliased before the anchored
691
+ * node is finished, so the parser hands out a BadAlias placeholder and only
692
+ * later learns which object the anchor really is. Only containers can hold a
693
+ * placeholder, so the walk stops at anything else. `seen` must compare by
694
+ * identity, otherwise equal-but-distinct nodes collapse and cycles that are
695
+ * already in place would recurse forever.
696
+ */
697
+ static void
698
+ syck_swap_placeholder(VALUE obj, VALUE from, VALUE to, VALUE seen)
699
+ {
700
+ long i;
701
+ VALUE ivars;
702
+
703
+ if ( SPECIAL_CONST_P( obj ) || OBJ_FROZEN( obj ) ) return;
704
+
705
+ switch ( BUILTIN_TYPE( obj ) )
706
+ {
707
+ case T_ARRAY:
708
+ case T_HASH:
709
+ case T_STRUCT:
710
+ case T_OBJECT:
711
+ break;
712
+
713
+ default:
714
+ return;
715
+ }
716
+
717
+ if ( RTEST( rb_hash_lookup( seen, obj ) ) ) return;
718
+ rb_hash_aset( seen, obj, Qtrue );
719
+
720
+ switch ( BUILTIN_TYPE( obj ) )
721
+ {
722
+ case T_ARRAY:
723
+ for ( i = 0; i < RARRAY_LEN( obj ); i++ )
724
+ {
725
+ VALUE v = rb_ary_entry( obj, i );
726
+ if ( v == from ) rb_ary_store( obj, i, to );
727
+ else syck_swap_placeholder( v, from, to, seen );
728
+ }
729
+ break;
730
+
731
+ case T_HASH:
732
+ {
733
+ VALUE keys = rb_funcall( obj, s_keys, 0 );
734
+ for ( i = 0; i < RARRAY_LEN( keys ); i++ )
735
+ {
736
+ VALUE key = rb_ary_entry( keys, i );
737
+ VALUE val = rb_hash_aref( obj, key );
738
+
739
+ if ( key == from || val == from )
740
+ {
741
+ VALUE new_key = key == from ? to : key;
742
+ VALUE new_val = val == from ? to : val;
743
+
744
+ if ( new_key != key ) rb_hash_delete( obj, key );
745
+ rb_hash_aset( obj, new_key, new_val );
746
+ key = new_key;
747
+ val = new_val;
748
+ }
749
+
750
+ syck_swap_placeholder( key, from, to, seen );
751
+ syck_swap_placeholder( val, from, to, seen );
752
+ }
753
+ }
754
+ break;
755
+
756
+ case T_STRUCT:
757
+ for ( i = 0; i < RSTRUCT_LEN( obj ); i++ )
758
+ {
759
+ VALUE v = rb_struct_aref( obj, LONG2NUM( i ) );
760
+ if ( v == from ) rb_struct_aset( obj, LONG2NUM( i ), to );
761
+ else syck_swap_placeholder( v, from, to, seen );
762
+ }
763
+ break;
764
+
765
+ default:
766
+ break;
767
+ }
768
+
769
+ ivars = rb_obj_instance_variables( obj );
770
+ for ( i = 0; i < RARRAY_LEN( ivars ); i++ )
771
+ {
772
+ ID name = SYM2ID( rb_ary_entry( ivars, i ) );
773
+ VALUE v = rb_ivar_get( obj, name );
774
+ if ( v == from ) rb_ivar_set( obj, name, to );
775
+ else syck_swap_placeholder( v, from, to, seen );
776
+ }
777
+ }
639
778
 
640
779
  /*
641
780
  * {native mode} node handler
@@ -645,6 +784,7 @@ SYMID
645
784
  rb_syck_load_handler(SyckParser *p, SyckNode *n)
646
785
  {
647
786
  VALUE obj = Qnil;
787
+ VALUE node_wrapper;
648
788
  struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
649
789
  VALUE resolver = bonus->resolver;
650
790
  if ( NIL_P( resolver ) )
@@ -655,16 +795,32 @@ rb_syck_load_handler(SyckParser *p, SyckNode *n)
655
795
  /*
656
796
  * Create node,
657
797
  */
658
- obj = rb_funcall( resolver, s_node_import, 1, Data_Wrap_Struct( cNode, syck_node_mark, NULL, n ) );
798
+ node_wrapper = TypedData_Wrap_Struct( cNode, &syck_node_type_nofree, n );
799
+ obj = rb_funcall( resolver, s_node_import, 1, node_wrapper );
800
+
801
+ /*
802
+ * syck_hdlr_add_node frees `n` as soon as we return (handler.c:25, when
803
+ * the node has no anchor). Ruby may still keep `node_wrapper` reachable
804
+ * via a conservative GC root on the machine stack, so the next GC would
805
+ * call syck_node_mark() with a dangling SyckNode*. Zero the wrapper's
806
+ * data pointer to make the mark a no-op. See ruby/syck#50.
807
+ */
808
+ DATA_PTR( node_wrapper ) = NULL;
659
809
 
660
810
  /*
661
- * ID already set, let's alter the symbol table to accept the new object
811
+ * A placeholder was handed out for this node while it was still being
812
+ * parsed. Syck used to fuse the two by copying the real object over the
813
+ * placeholder's heap slot, which is wrong on every count the GC cares
814
+ * about: the slot is sized for the placeholder, the copied flags carry
815
+ * the source object's age bits, no write barrier fires, and zeroing the
816
+ * source turns a live object into T_NONE behind the GC's back. The heap
817
+ * then stays corrupted until some unrelated allocation crashes. Rewrite
818
+ * the references instead.
662
819
  */
663
820
  if (n->id > 0 && !NIL_P(obj))
664
821
  {
665
- MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
666
- MEMZERO((void *)obj, RVALUE, 1);
667
- obj = n->id;
822
+ syck_swap_placeholder( obj, (VALUE)n->id, obj, id_hash_new() );
823
+ n->id = obj;
668
824
  }
669
825
 
670
826
  if ( bonus->taint) OBJ_TAINT( obj );
@@ -701,7 +857,7 @@ rb_syck_bad_anchor_handler(SyckParser *p, char *a)
701
857
  {
702
858
  VALUE anchor_name = rb_str_new2( a );
703
859
  SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), anchor_name );
704
- badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
860
+ badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 50 );
705
861
  return badanc;
706
862
  }
707
863
 
@@ -712,7 +868,7 @@ void
712
868
  syck_set_model(VALUE p, VALUE input, VALUE model)
713
869
  {
714
870
  SyckParser *parser;
715
- Data_Get_Struct(p, SyckParser, parser);
871
+ TypedData_Get_Struct(p, SyckParser, &syck_parser_type, parser);
716
872
  syck_parser_handler( parser, rb_syck_load_handler );
717
873
  /* WARN: gonna be obsoleted soon!! */
718
874
  if ( model == sym_generic )
@@ -791,7 +947,7 @@ syck_parser_s_alloc(VALUE class)
791
947
  parser->bonus = S_ALLOC( struct parser_xtra );
792
948
  S_MEMZERO( parser->bonus, struct parser_xtra, 1 );
793
949
 
794
- pobj = Data_Wrap_Struct( class, syck_mark_parser, rb_syck_free_parser, parser );
950
+ pobj = TypedData_Wrap_Struct( class, &syck_parser_type, parser );
795
951
 
796
952
  syck_parser_set_root_on_error( parser, Qnil );
797
953
 
@@ -828,7 +984,7 @@ syck_parser_bufsize_set(VALUE self, VALUE size)
828
984
 
829
985
  if ( rb_respond_to( size, s_to_i ) ) {
830
986
  int n = NUM2INT(rb_funcall(size, s_to_i, 0));
831
- Data_Get_Struct(self, SyckParser, parser);
987
+ TypedData_Get_Struct(self, SyckParser, &syck_parser_type, parser);
832
988
  parser->bufsize = n;
833
989
  }
834
990
  return self;
@@ -842,7 +998,7 @@ syck_parser_bufsize_get(VALUE self)
842
998
  {
843
999
  SyckParser *parser;
844
1000
 
845
- Data_Get_Struct(self, SyckParser, parser);
1001
+ TypedData_Get_Struct(self, SyckParser, &syck_parser_type, parser);
846
1002
  return INT2FIX( parser->bufsize );
847
1003
  }
848
1004
 
@@ -860,7 +1016,7 @@ syck_parser_load(int argc, VALUE *argv, VALUE self)
860
1016
 
861
1017
  input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
862
1018
  model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
863
- Data_Get_Struct(self, SyckParser, parser);
1019
+ TypedData_Get_Struct(self, SyckParser, &syck_parser_type, parser);
864
1020
  syck_set_model( self, input, model );
865
1021
 
866
1022
  bonus = (struct parser_xtra *)parser->bonus;
@@ -887,7 +1043,7 @@ syck_parser_load_documents(int argc, VALUE *argv, VALUE self)
887
1043
 
888
1044
  input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
889
1045
  model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
890
- Data_Get_Struct(self, SyckParser, parser);
1046
+ TypedData_Get_Struct(self, SyckParser, &syck_parser_type, parser);
891
1047
  syck_set_model( self, input, model );
892
1048
 
893
1049
  bonus = (struct parser_xtra *)parser->bonus;
@@ -973,7 +1129,7 @@ syck_resolver_node_import(VALUE self, VALUE node)
973
1129
  SyckNode *n;
974
1130
  VALUE obj = Qnil;
975
1131
  int i = 0;
976
- Data_Get_Struct(node, SyckNode, n);
1132
+ TypedData_Get_Struct(node, SyckNode, &syck_node_type, n);
977
1133
 
978
1134
  switch (n->kind)
979
1135
  {
@@ -1264,7 +1420,7 @@ syck_defaultresolver_node_import(VALUE self, VALUE node)
1264
1420
  {
1265
1421
  SyckNode *n;
1266
1422
  VALUE obj;
1267
- Data_Get_Struct( node, SyckNode, n );
1423
+ TypedData_Get_Struct( node, SyckNode, &syck_node_type, n );
1268
1424
  if ( !yaml_org_handler( n, &obj ) )
1269
1425
  {
1270
1426
  obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
@@ -1281,7 +1437,7 @@ syck_genericresolver_node_import(VALUE self, VALUE node)
1281
1437
  SyckNode *n;
1282
1438
  int i = 0;
1283
1439
  VALUE t = Qnil, obj = Qnil, v = Qnil, style = Qnil;
1284
- Data_Get_Struct(node, SyckNode, n);
1440
+ TypedData_Get_Struct(node, SyckNode, &syck_node_type, n);
1285
1441
 
1286
1442
  if ( n->type_id != NULL )
1287
1443
  {
@@ -1413,6 +1569,7 @@ static void
1413
1569
  syck_node_mark(SyckNode *n)
1414
1570
  {
1415
1571
  int i;
1572
+ if ( n == NULL ) return;
1416
1573
  rb_gc_mark_maybe( n->id );
1417
1574
  switch ( n->kind )
1418
1575
  {
@@ -1448,7 +1605,7 @@ VALUE
1448
1605
  syck_scalar_alloc(VALUE class)
1449
1606
  {
1450
1607
  SyckNode *node = syck_alloc_str();
1451
- VALUE obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
1608
+ VALUE obj = TypedData_Wrap_Struct( class, &syck_node_type, node );
1452
1609
  node->id = obj;
1453
1610
  return obj;
1454
1611
  }
@@ -1473,7 +1630,7 @@ VALUE
1473
1630
  syck_scalar_style_set(VALUE self, VALUE style)
1474
1631
  {
1475
1632
  SyckNode *node;
1476
- Data_Get_Struct( self, SyckNode, node );
1633
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1477
1634
 
1478
1635
  if ( NIL_P( style ) )
1479
1636
  {
@@ -1511,7 +1668,7 @@ VALUE
1511
1668
  syck_scalar_value_set(VALUE self, VALUE val)
1512
1669
  {
1513
1670
  SyckNode *node;
1514
- Data_Get_Struct( self, SyckNode, node );
1671
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1515
1672
 
1516
1673
  StringValue( val );
1517
1674
  node->data.str->ptr = syck_strndup( RSTRING_PTR(val), RSTRING_LEN(val) );
@@ -1531,7 +1688,7 @@ syck_seq_alloc(VALUE class)
1531
1688
  SyckNode *node;
1532
1689
  VALUE obj;
1533
1690
  node = syck_alloc_seq();
1534
- obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
1691
+ obj = TypedData_Wrap_Struct( class, &syck_node_type, node );
1535
1692
  node->id = obj;
1536
1693
  return obj;
1537
1694
  }
@@ -1543,7 +1700,7 @@ VALUE
1543
1700
  syck_seq_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
1544
1701
  {
1545
1702
  SyckNode *node;
1546
- Data_Get_Struct( self, SyckNode, node );
1703
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1547
1704
 
1548
1705
  rb_iv_set( self, "@kind", sym_seq );
1549
1706
  rb_funcall( self, s_type_id_set, 1, type_id );
@@ -1559,7 +1716,7 @@ VALUE
1559
1716
  syck_seq_value_set(VALUE self, VALUE val)
1560
1717
  {
1561
1718
  SyckNode *node;
1562
- Data_Get_Struct( self, SyckNode, node );
1719
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1563
1720
 
1564
1721
  val = rb_check_array_type( val );
1565
1722
  if ( !NIL_P( val ) ) {
@@ -1583,7 +1740,7 @@ syck_seq_add_m(VALUE self, VALUE val)
1583
1740
  {
1584
1741
  SyckNode *node;
1585
1742
  VALUE emitter = rb_ivar_get( self, s_emitter );
1586
- Data_Get_Struct( self, SyckNode, node );
1743
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1587
1744
 
1588
1745
  if ( rb_respond_to( emitter, s_node_export ) ) {
1589
1746
  val = rb_funcall( emitter, s_node_export, 1, val );
@@ -1601,7 +1758,7 @@ VALUE
1601
1758
  syck_seq_style_set(VALUE self, VALUE style)
1602
1759
  {
1603
1760
  SyckNode *node;
1604
- Data_Get_Struct( self, SyckNode, node );
1761
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1605
1762
 
1606
1763
  if ( style == sym_inline )
1607
1764
  {
@@ -1625,7 +1782,7 @@ syck_map_alloc(VALUE class)
1625
1782
  SyckNode *node;
1626
1783
  VALUE obj;
1627
1784
  node = syck_alloc_map();
1628
- obj = Data_Wrap_Struct( class, syck_node_mark, syck_free_node, node );
1785
+ obj = TypedData_Wrap_Struct( class, &syck_node_type, node );
1629
1786
  node->id = obj;
1630
1787
  return obj;
1631
1788
  }
@@ -1637,7 +1794,7 @@ VALUE
1637
1794
  syck_map_initialize(VALUE self, VALUE type_id, VALUE val, VALUE style)
1638
1795
  {
1639
1796
  SyckNode *node;
1640
- Data_Get_Struct( self, SyckNode, node );
1797
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1641
1798
 
1642
1799
  if ( !NIL_P( val ) )
1643
1800
  {
@@ -1671,7 +1828,7 @@ VALUE
1671
1828
  syck_map_value_set(VALUE self, VALUE val)
1672
1829
  {
1673
1830
  SyckNode *node;
1674
- Data_Get_Struct( self, SyckNode, node );
1831
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1675
1832
 
1676
1833
  if ( !NIL_P( val ) )
1677
1834
  {
@@ -1704,7 +1861,7 @@ syck_map_add_m(VALUE self, VALUE key, VALUE val)
1704
1861
  {
1705
1862
  SyckNode *node;
1706
1863
  VALUE emitter = rb_ivar_get( self, s_emitter );
1707
- Data_Get_Struct( self, SyckNode, node );
1864
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1708
1865
 
1709
1866
  if ( rb_respond_to( emitter, s_node_export ) ) {
1710
1867
  key = rb_funcall( emitter, s_node_export, 1, key );
@@ -1723,7 +1880,7 @@ VALUE
1723
1880
  syck_map_style_set(VALUE self, VALUE style)
1724
1881
  {
1725
1882
  SyckNode *node;
1726
- Data_Get_Struct( self, SyckNode, node );
1883
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1727
1884
 
1728
1885
  if ( style == sym_inline )
1729
1886
  {
@@ -1756,8 +1913,8 @@ syck_node_init_copy(VALUE copy, VALUE orig)
1756
1913
  rb_raise( rb_eTypeError, "wrong argument type" );
1757
1914
  }
1758
1915
 
1759
- Data_Get_Struct( orig, SyckNode, orig_n );
1760
- Data_Get_Struct( copy, SyckNode, copy_n );
1916
+ TypedData_Get_Struct( orig, SyckNode, &syck_node_type, orig_n );
1917
+ TypedData_Get_Struct( copy, SyckNode, &syck_node_type, copy_n );
1761
1918
  MEMCPY( copy_n, orig_n, SyckNode, 1 );
1762
1919
  return copy;
1763
1920
  }
@@ -1770,7 +1927,7 @@ VALUE
1770
1927
  syck_node_type_id_set(VALUE self, VALUE type_id)
1771
1928
  {
1772
1929
  SyckNode *node;
1773
- Data_Get_Struct( self, SyckNode, node );
1930
+ TypedData_Get_Struct( self, SyckNode, &syck_node_type, node );
1774
1931
 
1775
1932
  S_FREE( node->type_id );
1776
1933
 
@@ -1792,8 +1949,8 @@ syck_node_transform(VALUE self)
1792
1949
  VALUE t;
1793
1950
  SyckNode *n = NULL;
1794
1951
  SyckNode *orig_n;
1795
- Data_Get_Struct(self, SyckNode, orig_n);
1796
- t = Data_Wrap_Struct( cNode, syck_node_mark, syck_free_node, 0 );
1952
+ TypedData_Get_Struct(self, SyckNode, &syck_node_type, orig_n);
1953
+ t = TypedData_Wrap_Struct( cNode, &syck_node_type, 0 );
1797
1954
 
1798
1955
  switch (orig_n->kind)
1799
1956
  {
@@ -1846,7 +2003,7 @@ void
1846
2003
  rb_syck_emitter_handler(SyckEmitter *e, st_data_t data)
1847
2004
  {
1848
2005
  SyckNode *n;
1849
- Data_Get_Struct((VALUE)data, SyckNode, n);
2006
+ TypedData_Get_Struct((VALUE)data, SyckNode, &syck_node_type, n);
1850
2007
 
1851
2008
  switch (n->kind)
1852
2009
  {
@@ -1907,7 +2064,7 @@ syck_out_mark(VALUE emitter, VALUE node)
1907
2064
  {
1908
2065
  SyckEmitter *emitterPtr;
1909
2066
  struct emitter_xtra *bonus;
1910
- Data_Get_Struct(emitter, SyckEmitter, emitterPtr);
2067
+ TypedData_Get_Struct(emitter, SyckEmitter, &syck_emitter_type, emitterPtr);
1911
2068
  bonus = (struct emitter_xtra *)emitterPtr->bonus;
1912
2069
  rb_ivar_set( node, s_emitter, emitter );
1913
2070
  /* syck_emitter_mark_node( emitterPtr, (st_data_t)node ); */
@@ -1951,7 +2108,7 @@ syck_emitter_s_alloc(VALUE class)
1951
2108
  emitter->bonus = S_ALLOC( struct emitter_xtra );
1952
2109
  S_MEMZERO( emitter->bonus, struct emitter_xtra, 1 );
1953
2110
 
1954
- pobj = Data_Wrap_Struct( class, syck_mark_emitter, rb_syck_free_emitter, emitter );
2111
+ pobj = TypedData_Wrap_Struct( class, &syck_emitter_type, emitter );
1955
2112
  syck_emitter_handler( emitter, rb_syck_emitter_handler );
1956
2113
  syck_output_handler( emitter, rb_syck_output_handler );
1957
2114
 
@@ -1978,7 +2135,7 @@ syck_emitter_reset(int argc, VALUE *argv, VALUE self)
1978
2135
  SyckEmitter *emitter;
1979
2136
  struct emitter_xtra *bonus;
1980
2137
 
1981
- Data_Get_Struct(self, SyckEmitter, emitter);
2138
+ TypedData_Get_Struct(self, SyckEmitter, &syck_emitter_type, emitter);
1982
2139
  bonus = (struct emitter_xtra *)emitter->bonus;
1983
2140
 
1984
2141
  bonus->oid = Qnil;
@@ -2024,7 +2181,7 @@ syck_emitter_emit(int argc, VALUE *argv, VALUE self)
2024
2181
  rb_ivar_set(self, s_level, INT2FIX(level));
2025
2182
 
2026
2183
  rb_scan_args(argc, argv, "1&", &oid, &proc);
2027
- Data_Get_Struct(self, SyckEmitter, emitter);
2184
+ TypedData_Get_Struct(self, SyckEmitter, &syck_emitter_type, emitter);
2028
2185
  bonus = (struct emitter_xtra *)emitter->bonus;
2029
2186
 
2030
2187
  /* Calculate anchors, normalize nodes, build a simpler symbol table */
data/ext/syck/yaml2byte.c CHANGED
@@ -115,9 +115,7 @@ void bytestring_extend(bytestring_t *str, bytestring_t *ext)
115
115
 
116
116
  /* convert SyckNode into yamlbyte_buffer_t objects */
117
117
  SYMID
118
- syck_yaml2byte_handler(p, n)
119
- SyckParser *p;
120
- SyckNode *n;
118
+ syck_yaml2byte_handler(SyckParser *p, SyckNode *n)
121
119
  {
122
120
  SYMID oid;
123
121
  long i;
@@ -6,7 +6,7 @@ module Syck
6
6
  #
7
7
  # Constants
8
8
  #
9
- VERSION = '1.5.1.1'
9
+ VERSION = '1.6.1'
10
10
  SUPPORTED_YAML_VERSIONS = ['1.0']
11
11
 
12
12
  #
data/test/test_boolean.rb CHANGED
@@ -32,5 +32,17 @@ module Syck
32
32
  assert_equal "n", Syck.load("--- n")
33
33
  assert_equal "N", Syck.load("--- N")
34
34
  end
35
+
36
+ ###
37
+ # https://github.com/ruby/syck/issues/22
38
+ # A boolean-like prefix followed by a non-ASCII byte must not be
39
+ # matched as a boolean
40
+ def test_bool_prefix_with_non_ascii
41
+ assert_equal "Noémie", Syck.load("--- Noémie")
42
+ assert_equal ["Noémie"], Syck.load("--- [Noémie]")
43
+ assert_equal "Yeså", Syck.load("--- Yeså")
44
+ assert_equal "trueé", Syck.load("--- trueé")
45
+ assert_equal "nullé", Syck.load("--- nullé")
46
+ end
35
47
  end
36
48
  end
data/test/test_gc.rb ADDED
@@ -0,0 +1,33 @@
1
+ require_relative "helper"
2
+
3
+ # Regression test for ruby/syck#50 - heap-use-after-free in syck_node_mark
4
+ # when GC runs between syck_hdlr_add_node freeing a SyckNode and the Ruby
5
+ # Data wrapper that pointed at it being collected.
6
+ #
7
+ # GC.stress forces a full GC on every allocation, so if the fix regresses
8
+ # this test will segfault (or fire under ASAN/valgrind).
9
+ class TestGC < Test::Unit::TestCase
10
+ def test_load_under_gc_stress
11
+ yaml = ({}.tap { |h| 50.times { |i| h["k#{i}"] = "v" * 64 } }).to_yaml
12
+
13
+ GC.stress = true
14
+ begin
15
+ 3.times { Syck.load(yaml) }
16
+ ensure
17
+ GC.stress = false
18
+ end
19
+ end
20
+
21
+ def test_load_many_documents_under_gc_stress
22
+ docs = Array.new(5) do |i|
23
+ ({}.tap { |h| 30.times { |k| h["k_#{i}_#{k}"] = "v_#{i}_#{k}" } }).to_yaml
24
+ end
25
+
26
+ GC.stress = true
27
+ begin
28
+ docs.each { |d| Syck.load(d) }
29
+ ensure
30
+ GC.stress = false
31
+ end
32
+ end
33
+ end
data/test/test_yaml.rb CHANGED
@@ -1337,6 +1337,40 @@ EOY
1337
1337
  assert_equal( inspect_str, Syck::load( a.to_yaml ).inspect )
1338
1338
  end
1339
1339
 
1340
+ #
1341
+ # A self-referential anchor is aliased before the anchored node exists, so
1342
+ # the parser hands out a placeholder and patches it up afterwards. That
1343
+ # used to be done by overwriting the placeholder's heap slot, which left
1344
+ # the GC heap corrupted and crashed at some later allocation.
1345
+ #
1346
+ def test_self_referential_anchor
1347
+ [ 1, 3, 6, 50 ].each do |n|
1348
+ seq = Syck::load( "--- &id001\n" + "- *id001\n" * n )
1349
+ assert_equal( n, seq.size )
1350
+ seq.each { |item| assert_same( seq, item ) }
1351
+ end
1352
+
1353
+ map = Syck::load( "--- &id001\nself: *id001\n" )
1354
+ assert_same( map, map["self"] )
1355
+
1356
+ keyed = Syck::load( "--- &id001\n? *id001\n: 1\n" )
1357
+ assert_same( keyed, keyed.keys.first )
1358
+
1359
+ # The alias appears as a key and again below the matching value, so
1360
+ # rewriting the key must not stop the walk from reaching the rest.
1361
+ both = Syck::load( "--- &id001\n? *id001\n: \n - *id001\n" )
1362
+ key, value = both.first
1363
+ assert_same( both, key )
1364
+ assert_same( both, value[0] )
1365
+
1366
+ nested = Syck::load( "--- &id001\n- &id002\n - *id001\n- *id002\n" )
1367
+ assert_same( nested, nested[0][0] )
1368
+ assert_same( nested[0], nested[1] )
1369
+
1370
+ GC.start
1371
+ assert_nothing_raised { GC.verify_internal_consistency }
1372
+ end
1373
+
1340
1374
  #
1341
1375
  # Test Symbol cycle
1342
1376
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syck
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1.1
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroshi SHIBATA
@@ -9,7 +9,7 @@ authors:
9
9
  - Mat Brown
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-08-19 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -100,12 +100,12 @@ files:
100
100
  - lib/syck/yamlnode.rb
101
101
  - lib/syck/ypath.rb
102
102
  - lib/yaml/syck.rb
103
- - syck.gemspec
104
103
  - test/helper.rb
105
104
  - test/test_array.rb
106
105
  - test/test_boolean.rb
107
106
  - test/test_class.rb
108
107
  - test/test_exception.rb
108
+ - test/test_gc.rb
109
109
  - test/test_hash.rb
110
110
  - test/test_null.rb
111
111
  - test/test_omap.rb
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  - !ruby/object:Gem::Version
137
137
  version: 0.9.5
138
138
  requirements: []
139
- rubygems_version: 3.6.0.dev
139
+ rubygems_version: 3.6.9
140
140
  specification_version: 4
141
141
  summary: A gemified version of Syck from Ruby's stdlib
142
142
  test_files:
@@ -145,6 +145,7 @@ test_files:
145
145
  - test/test_boolean.rb
146
146
  - test/test_class.rb
147
147
  - test/test_exception.rb
148
+ - test/test_gc.rb
148
149
  - test/test_hash.rb
149
150
  - test/test_null.rb
150
151
  - test/test_omap.rb
data/syck.gemspec DELETED
@@ -1,26 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- Gem::Specification.new do |s|
4
- s.name = "syck"
5
- s.version = "1.5.1.1"
6
-
7
- s.summary = "A gemified version of Syck from Ruby's stdlib"
8
- s.description = "A gemified version of Syck from Ruby's stdlib. Syck has been removed from\nRuby's stdlib, and this gem is meant to bridge the gap for people that haven't\nupdated their YAML yet."
9
- s.authors = ["Hiroshi SHIBATA", "Aaron Patterson", "Mat Brown"]
10
- s.email = ["hsbt@ruby-lang.org", "aaron@tenderlovemaking.com"]
11
- s.homepage = "https://github.com/ruby/syck"
12
- s.license = "MIT"
13
- s.require_paths = ["lib"]
14
- s.extensions = ["ext/syck/extconf.rb"]
15
- s.files = Dir["[A-Z]*", "ext/**/*", "lib/**/*.rb", "test/**/*.rb"] - %w[Gemfile.lock ext/syck/gram.y]
16
- s.extra_rdoc_files = ["README.rdoc"]
17
- s.test_files = Dir["test/**/*.rb"]
18
- s.rdoc_options = ["--main", "README.rdoc"]
19
- s.required_ruby_version = Gem::Requirement.new(">= 2.0.0")
20
- s.required_rubygems_version = Gem::Requirement.new(">= 0.9.5")
21
- s.rubygems_version = "2.0.3"
22
-
23
- s.add_development_dependency(%q<bundler>)
24
- s.add_development_dependency(%q<test-unit>)
25
- s.add_development_dependency(%q<rake-compiler>)
26
- end