kanayago 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +15 -0
  3. data/.rubocop_todo.yml +23 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +79 -0
  6. data/Rakefile +182 -0
  7. data/ext/kanayago/ccan/check_type/check_type.h +63 -0
  8. data/ext/kanayago/ccan/container_of/container_of.h +142 -0
  9. data/ext/kanayago/ccan/list/list.h +791 -0
  10. data/ext/kanayago/ccan/str/str.h +17 -0
  11. data/ext/kanayago/constant.h +53 -0
  12. data/ext/kanayago/extconf.rb +21 -0
  13. data/ext/kanayago/id.h +347 -0
  14. data/ext/kanayago/id_table.h +39 -0
  15. data/ext/kanayago/internal/array.h +151 -0
  16. data/ext/kanayago/internal/basic_operators.h +64 -0
  17. data/ext/kanayago/internal/bignum.h +244 -0
  18. data/ext/kanayago/internal/bits.h +568 -0
  19. data/ext/kanayago/internal/compile.h +34 -0
  20. data/ext/kanayago/internal/compilers.h +107 -0
  21. data/ext/kanayago/internal/complex.h +29 -0
  22. data/ext/kanayago/internal/encoding.h +36 -0
  23. data/ext/kanayago/internal/error.h +218 -0
  24. data/ext/kanayago/internal/fixnum.h +184 -0
  25. data/ext/kanayago/internal/gc.h +322 -0
  26. data/ext/kanayago/internal/hash.h +191 -0
  27. data/ext/kanayago/internal/imemo.h +261 -0
  28. data/ext/kanayago/internal/io.h +140 -0
  29. data/ext/kanayago/internal/numeric.h +274 -0
  30. data/ext/kanayago/internal/parse.h +117 -0
  31. data/ext/kanayago/internal/rational.h +71 -0
  32. data/ext/kanayago/internal/re.h +28 -0
  33. data/ext/kanayago/internal/ruby_parser.h +125 -0
  34. data/ext/kanayago/internal/sanitizers.h +297 -0
  35. data/ext/kanayago/internal/serial.h +23 -0
  36. data/ext/kanayago/internal/static_assert.h +16 -0
  37. data/ext/kanayago/internal/string.h +186 -0
  38. data/ext/kanayago/internal/symbol.h +45 -0
  39. data/ext/kanayago/internal/thread.h +79 -0
  40. data/ext/kanayago/internal/variable.h +72 -0
  41. data/ext/kanayago/internal/vm.h +137 -0
  42. data/ext/kanayago/internal/warnings.h +16 -0
  43. data/ext/kanayago/internal.h +108 -0
  44. data/ext/kanayago/kanayago.c +420 -0
  45. data/ext/kanayago/kanayago.h +21 -0
  46. data/ext/kanayago/lex.c +302 -0
  47. data/ext/kanayago/method.h +255 -0
  48. data/ext/kanayago/node.c +440 -0
  49. data/ext/kanayago/node.h +111 -0
  50. data/ext/kanayago/node_name.inc +224 -0
  51. data/ext/kanayago/parse.c +26931 -0
  52. data/ext/kanayago/parse.h +244 -0
  53. data/ext/kanayago/parse.tmp.y +16145 -0
  54. data/ext/kanayago/parser_bits.h +564 -0
  55. data/ext/kanayago/parser_node.h +32 -0
  56. data/ext/kanayago/parser_st.c +164 -0
  57. data/ext/kanayago/parser_st.h +162 -0
  58. data/ext/kanayago/parser_value.h +106 -0
  59. data/ext/kanayago/probes.h +4 -0
  60. data/ext/kanayago/ruby_assert.h +14 -0
  61. data/ext/kanayago/ruby_atomic.h +23 -0
  62. data/ext/kanayago/ruby_parser.c +1165 -0
  63. data/ext/kanayago/rubyparser.h +1391 -0
  64. data/ext/kanayago/shape.h +234 -0
  65. data/ext/kanayago/st.c +2339 -0
  66. data/ext/kanayago/symbol.h +123 -0
  67. data/ext/kanayago/thread_pthread.h +168 -0
  68. data/ext/kanayago/universal_parser.c +230 -0
  69. data/ext/kanayago/vm_core.h +2215 -0
  70. data/ext/kanayago/vm_opts.h +67 -0
  71. data/lib/kanayago/version.rb +5 -0
  72. data/lib/kanayago.rb +11 -0
  73. data/sig/kanayago.rbs +4 -0
  74. metadata +116 -0
@@ -0,0 +1,117 @@
1
+ #ifndef INTERNAL_PARSE_H /*-*-C-*-vi:se ft=c:*/
2
+ #define INTERNAL_PARSE_H
3
+ /**
4
+ * @author Ruby developers <ruby-core@ruby-lang.org>
5
+ * @copyright This file is a part of the programming language Ruby.
6
+ * Permission is hereby granted, to either redistribute and/or
7
+ * modify this file, provided that the conditions mentioned in the
8
+ * file COPYING are met. Consult the file for details.
9
+ * @brief Internal header for the parser.
10
+ */
11
+ #include <limits.h>
12
+ #include "rubyparser.h"
13
+ #include "internal/static_assert.h"
14
+
15
+ #ifdef UNIVERSAL_PARSER
16
+ #define rb_encoding const void
17
+ #endif
18
+
19
+ struct rb_iseq_struct; /* in vm_core.h */
20
+
21
+ /* structs for managing terminator of string literal and heredocment */
22
+ typedef struct rb_strterm_literal_struct {
23
+ long nest;
24
+ int func; /* STR_FUNC_* (e.g., STR_FUNC_ESCAPE and STR_FUNC_EXPAND) */
25
+ int paren; /* '(' of `%q(...)` */
26
+ int term; /* ')' of `%q(...)` */
27
+ } rb_strterm_literal_t;
28
+
29
+ typedef struct rb_strterm_heredoc_struct {
30
+ rb_parser_string_t *lastline; /* the string of line that contains `<<"END"` */
31
+ long offset; /* the column of END in `<<"END"` */
32
+ int sourceline; /* lineno of the line that contains `<<"END"` */
33
+ unsigned length; /* the length of END in `<<"END"` */
34
+ uint8_t quote;
35
+ uint8_t func;
36
+ } rb_strterm_heredoc_t;
37
+
38
+ #define HERETERM_LENGTH_MAX UINT_MAX
39
+
40
+ typedef struct rb_strterm_struct {
41
+ bool heredoc;
42
+ union {
43
+ rb_strterm_literal_t literal;
44
+ rb_strterm_heredoc_t heredoc;
45
+ } u;
46
+ } rb_strterm_t;
47
+
48
+ /* parse.y */
49
+ void rb_ruby_parser_mark(void *ptr);
50
+ size_t rb_ruby_parser_memsize(const void *ptr);
51
+
52
+ void rb_ruby_parser_set_options(rb_parser_t *p, int print, int loop, int chomp, int split);
53
+ rb_parser_t *rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, int main);
54
+ void rb_ruby_parser_set_script_lines(rb_parser_t *p);
55
+ void rb_ruby_parser_error_tolerant(rb_parser_t *p);
56
+ void rb_ruby_parser_keep_tokens(rb_parser_t *p);
57
+ typedef rb_parser_string_t*(rb_parser_lex_gets_func)(struct parser_params*, rb_parser_input_data, int);
58
+ rb_ast_t *rb_parser_compile(rb_parser_t *p, rb_parser_lex_gets_func *gets, VALUE fname, rb_parser_input_data input, int line);
59
+
60
+ RUBY_SYMBOL_EXPORT_BEGIN
61
+
62
+ rb_encoding *rb_ruby_parser_encoding(rb_parser_t *p);
63
+ int rb_ruby_parser_end_seen_p(rb_parser_t *p);
64
+ int rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag);
65
+ rb_parser_string_t *rb_str_to_parser_string(rb_parser_t *p, VALUE str);
66
+
67
+ int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**);
68
+ ID rb_parser_internal_id(struct parser_params*);
69
+ int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
70
+ int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc);
71
+ int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq);
72
+
73
+ RUBY_SYMBOL_EXPORT_END
74
+
75
+ #ifndef UNIVERSAL_PARSER
76
+ rb_parser_t *rb_ruby_parser_allocate(void);
77
+ rb_parser_t *rb_ruby_parser_new(void);
78
+ #endif
79
+
80
+ #ifdef RIPPER
81
+ void ripper_parser_mark(void *ptr);
82
+ void ripper_parser_free(void *ptr);
83
+ size_t ripper_parser_memsize(const void *ptr);
84
+ void ripper_error(struct parser_params *p);
85
+ VALUE ripper_value(struct parser_params *p);
86
+ int rb_ruby_parser_get_yydebug(rb_parser_t *p);
87
+ void rb_ruby_parser_set_value(rb_parser_t *p, VALUE value);
88
+ int rb_ruby_parser_error_p(rb_parser_t *p);
89
+ VALUE rb_ruby_parser_debug_output(rb_parser_t *p);
90
+ void rb_ruby_parser_set_debug_output(rb_parser_t *p, VALUE output);
91
+ VALUE rb_ruby_parser_parsing_thread(rb_parser_t *p);
92
+ void rb_ruby_parser_set_parsing_thread(rb_parser_t *p, VALUE parsing_thread);
93
+ void rb_ruby_parser_ripper_initialize(rb_parser_t *p, rb_parser_lex_gets_func *gets, rb_parser_input_data input, VALUE sourcefile_string, const char *sourcefile, int sourceline);
94
+ VALUE rb_ruby_parser_result(rb_parser_t *p);
95
+ rb_encoding *rb_ruby_parser_enc(rb_parser_t *p);
96
+ VALUE rb_ruby_parser_ruby_sourcefile_string(rb_parser_t *p);
97
+ int rb_ruby_parser_ruby_sourceline(rb_parser_t *p);
98
+ int rb_ruby_parser_lex_state(rb_parser_t *p);
99
+ void rb_ruby_ripper_parse0(rb_parser_t *p);
100
+ int rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width);
101
+ int rb_ruby_ripper_initialized_p(rb_parser_t *p);
102
+ void rb_ruby_ripper_parser_initialize(rb_parser_t *p);
103
+ long rb_ruby_ripper_column(rb_parser_t *p);
104
+ long rb_ruby_ripper_token_len(rb_parser_t *p);
105
+ rb_parser_string_t *rb_ruby_ripper_lex_lastline(rb_parser_t *p);
106
+ VALUE rb_ruby_ripper_lex_state_name(struct parser_params *p, int state);
107
+ #ifdef UNIVERSAL_PARSER
108
+ rb_parser_t *rb_ripper_parser_params_allocate(const rb_parser_config_t *config);
109
+ #endif
110
+ struct parser_params *rb_ruby_ripper_parser_allocate(void);
111
+ #endif
112
+
113
+ #ifdef UNIVERSAL_PARSER
114
+ #undef rb_encoding
115
+ #endif
116
+
117
+ #endif /* INTERNAL_PARSE_H */
@@ -0,0 +1,71 @@
1
+ #ifndef INTERNAL_RATIONAL_H /*-*-C-*-vi:se ft=c:*/
2
+ #define INTERNAL_RATIONAL_H
3
+ /**
4
+ * @author Ruby developers <ruby-core@ruby-lang.org>
5
+ * @copyright This file is a part of the programming language Ruby.
6
+ * Permission is hereby granted, to either redistribute and/or
7
+ * modify this file, provided that the conditions mentioned in the
8
+ * file COPYING are met. Consult the file for details.
9
+ * @brief Internal header for Rational.
10
+ */
11
+ #include "ruby/internal/config.h" /* for HAVE_LIBGMP */
12
+ #include "ruby/ruby.h" /* for struct RBasic */
13
+ #include "internal/numeric.h" /* for INT_POSITIVE_P */
14
+ #include "ruby_assert.h" /* for assert */
15
+
16
+ struct RRational {
17
+ struct RBasic basic;
18
+ VALUE num;
19
+ VALUE den;
20
+ };
21
+
22
+ #define RRATIONAL(obj) ((struct RRational *)(obj))
23
+
24
+ /* rational.c */
25
+ VALUE rb_rational_canonicalize(VALUE x);
26
+ VALUE rb_rational_uminus(VALUE self);
27
+ VALUE rb_rational_plus(VALUE self, VALUE other);
28
+ VALUE rb_rational_minus(VALUE self, VALUE other);
29
+ VALUE rb_rational_mul(VALUE self, VALUE other);
30
+ VALUE rb_rational_div(VALUE self, VALUE other);
31
+ VALUE rb_lcm(VALUE x, VALUE y);
32
+ VALUE rb_rational_reciprocal(VALUE x);
33
+ VALUE rb_cstr_to_rat(const char *, int);
34
+ VALUE rb_rational_hash(VALUE self);
35
+ VALUE rb_rational_abs(VALUE self);
36
+ VALUE rb_rational_cmp(VALUE self, VALUE other);
37
+ VALUE rb_rational_pow(VALUE self, VALUE other);
38
+ VALUE rb_rational_floor(VALUE self, int ndigits);
39
+ VALUE rb_numeric_quo(VALUE x, VALUE y);
40
+ VALUE rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num);
41
+ VALUE rb_float_numerator(VALUE x);
42
+ VALUE rb_float_denominator(VALUE x);
43
+
44
+ static inline void RATIONAL_SET_NUM(VALUE r, VALUE n);
45
+ static inline void RATIONAL_SET_DEN(VALUE r, VALUE d);
46
+
47
+ RUBY_SYMBOL_EXPORT_BEGIN
48
+ /* rational.c (export) */
49
+ VALUE rb_gcd(VALUE x, VALUE y);
50
+ VALUE rb_gcd_normal(VALUE self, VALUE other);
51
+ #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
52
+ VALUE rb_gcd_gmp(VALUE x, VALUE y);
53
+ #endif
54
+ RUBY_SYMBOL_EXPORT_END
55
+
56
+ static inline void
57
+ RATIONAL_SET_NUM(VALUE r, VALUE n)
58
+ {
59
+ assert(RB_INTEGER_TYPE_P(n));
60
+ RB_OBJ_WRITE(r, &RRATIONAL(r)->num, n);
61
+ }
62
+
63
+ static inline void
64
+ RATIONAL_SET_DEN(VALUE r, VALUE d)
65
+ {
66
+ assert(RB_INTEGER_TYPE_P(d));
67
+ assert(INT_POSITIVE_P(d));
68
+ RB_OBJ_WRITE(r, &RRATIONAL(r)->den, d);
69
+ }
70
+
71
+ #endif /* INTERNAL_RATIONAL_H */
@@ -0,0 +1,28 @@
1
+ #ifndef INTERNAL_RE_H /*-*-C-*-vi:se ft=c:*/
2
+ #define INTERNAL_RE_H
3
+ /**
4
+ * @author Ruby developers <ruby-core@ruby-lang.org>
5
+ * @copyright This file is a part of the programming language Ruby.
6
+ * Permission is hereby granted, to either redistribute and/or
7
+ * modify this file, provided that the conditions mentioned in the
8
+ * file COPYING are met. Consult the file for details.
9
+ * @brief Internal header for Regexp.
10
+ */
11
+ #include "ruby/internal/stdbool.h" /* for bool */
12
+ #include "ruby/ruby.h" /* for VALUE */
13
+
14
+ /* re.c */
15
+ VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline);
16
+ VALUE rb_reg_check_preprocess(VALUE);
17
+ long rb_reg_search0(VALUE, VALUE, long, int, int);
18
+ VALUE rb_reg_match_p(VALUE re, VALUE str, long pos);
19
+ bool rb_reg_start_with_p(VALUE re, VALUE str);
20
+ VALUE rb_reg_hash(VALUE re);
21
+ VALUE rb_reg_equal(VALUE re1, VALUE re2);
22
+ void rb_backref_set_string(VALUE string, long pos, long len);
23
+ void rb_match_unbusy(VALUE);
24
+ int rb_match_count(VALUE match);
25
+ VALUE rb_reg_new_ary(VALUE ary, int options);
26
+ VALUE rb_reg_last_defined(VALUE match);
27
+
28
+ #endif /* INTERNAL_RE_H */
@@ -0,0 +1,125 @@
1
+ #ifndef INTERNAL_RUBY_PARSE_H
2
+ #define INTERNAL_RUBY_PARSE_H
3
+
4
+ #include "internal.h"
5
+ #include "internal/bignum.h"
6
+ #include "internal/compilers.h"
7
+ #include "internal/complex.h"
8
+ #include "internal/parse.h"
9
+ #include "internal/rational.h"
10
+ #include "rubyparser.h"
11
+ #include "vm.h"
12
+
13
+ struct lex_pointer_string {
14
+ VALUE str;
15
+ long ptr;
16
+ };
17
+
18
+ // Add Ruby's Parser struct and enum for Kanayago
19
+ enum lex_type {
20
+ lex_type_str,
21
+ lex_type_io,
22
+ lex_type_array,
23
+ lex_type_generic,
24
+ };
25
+
26
+ struct ruby_parser {
27
+ rb_parser_t *parser_params;
28
+ enum lex_type type;
29
+ union {
30
+ struct lex_pointer_string lex_str;
31
+ struct {
32
+ VALUE file;
33
+ } lex_io;
34
+ struct {
35
+ VALUE ary;
36
+ } lex_array;
37
+ } data;
38
+ };
39
+ // End for Kanayago
40
+
41
+ RUBY_SYMBOL_EXPORT_BEGIN
42
+ #ifdef UNIVERSAL_PARSER
43
+ const rb_parser_config_t *rb_ruby_parser_config(void);
44
+ rb_parser_t *rb_parser_params_new(void);
45
+ #endif
46
+ VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
47
+ VALUE rb_parser_new(void);
48
+ VALUE rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line);
49
+ VALUE rb_str_new_parser_string(rb_parser_string_t *str);
50
+ VALUE rb_str_new_mutable_parser_string(rb_parser_string_t *str);
51
+ rb_parser_string_t *rb_parser_lex_get_str(struct parser_params *p, struct lex_pointer_string *ptr_str);
52
+
53
+ VALUE rb_node_str_string_val(const NODE *);
54
+ VALUE rb_node_sym_string_val(const NODE *);
55
+ VALUE rb_node_dstr_string_val(const NODE *);
56
+ VALUE rb_node_regx_string_val(const NODE *);
57
+ VALUE rb_node_dregx_string_val(const NODE *);
58
+ VALUE rb_node_line_lineno_val(const NODE *);
59
+ VALUE rb_node_file_path_val(const NODE *);
60
+ VALUE rb_node_encoding_val(const NODE *);
61
+
62
+ VALUE rb_node_integer_literal_val(const NODE *);
63
+ VALUE rb_node_float_literal_val(const NODE *);
64
+ VALUE rb_node_rational_literal_val(const NODE *);
65
+ VALUE rb_node_imaginary_literal_val(const NODE *);
66
+ RUBY_SYMBOL_EXPORT_END
67
+
68
+ VALUE rb_parser_end_seen_p(VALUE);
69
+ VALUE rb_parser_encoding(VALUE);
70
+ VALUE rb_parser_set_yydebug(VALUE, VALUE);
71
+ VALUE rb_parser_build_script_lines_from(rb_parser_ary_t *script_lines);
72
+ void rb_parser_set_options(VALUE, int, int, int, int);
73
+ VALUE rb_parser_load_file(VALUE parser, VALUE name);
74
+ void rb_parser_set_script_lines(VALUE vparser);
75
+ void rb_parser_error_tolerant(VALUE vparser);
76
+ void rb_parser_keep_tokens(VALUE vparser);
77
+
78
+ VALUE rb_parser_compile_string(VALUE, const char*, VALUE, int);
79
+ VALUE rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line);
80
+ VALUE rb_parser_compile_generic(VALUE vparser, rb_parser_lex_gets_func *lex_gets, VALUE fname, VALUE input, int line);
81
+ VALUE rb_parser_compile_array(VALUE vparser, VALUE fname, VALUE array, int start);
82
+
83
+ enum lex_state_bits {
84
+ EXPR_BEG_bit, /* ignore newline, +/- is a sign. */
85
+ EXPR_END_bit, /* newline significant, +/- is an operator. */
86
+ EXPR_ENDARG_bit, /* ditto, and unbound braces. */
87
+ EXPR_ENDFN_bit, /* ditto, and unbound braces. */
88
+ EXPR_ARG_bit, /* newline significant, +/- is an operator. */
89
+ EXPR_CMDARG_bit, /* newline significant, +/- is an operator. */
90
+ EXPR_MID_bit, /* newline significant, +/- is an operator. */
91
+ EXPR_FNAME_bit, /* ignore newline, no reserved words. */
92
+ EXPR_DOT_bit, /* right after `.', `&.' or `::', no reserved words. */
93
+ EXPR_CLASS_bit, /* immediate after `class', no here document. */
94
+ EXPR_LABEL_bit, /* flag bit, label is allowed. */
95
+ EXPR_LABELED_bit, /* flag bit, just after a label. */
96
+ EXPR_FITEM_bit, /* symbol literal as FNAME. */
97
+ EXPR_MAX_STATE
98
+ };
99
+ /* examine combinations */
100
+ enum lex_state_e {
101
+ #define DEF_EXPR(n) EXPR_##n = (1 << EXPR_##n##_bit)
102
+ DEF_EXPR(BEG),
103
+ DEF_EXPR(END),
104
+ DEF_EXPR(ENDARG),
105
+ DEF_EXPR(ENDFN),
106
+ DEF_EXPR(ARG),
107
+ DEF_EXPR(CMDARG),
108
+ DEF_EXPR(MID),
109
+ DEF_EXPR(FNAME),
110
+ DEF_EXPR(DOT),
111
+ DEF_EXPR(CLASS),
112
+ DEF_EXPR(LABEL),
113
+ DEF_EXPR(LABELED),
114
+ DEF_EXPR(FITEM),
115
+ EXPR_VALUE = EXPR_BEG,
116
+ EXPR_BEG_ANY = (EXPR_BEG | EXPR_MID | EXPR_CLASS),
117
+ EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG),
118
+ EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN),
119
+ EXPR_NONE = 0
120
+ };
121
+
122
+ VALUE rb_ruby_ast_new(const NODE *const root);
123
+ rb_ast_t *rb_ruby_ast_data_get(VALUE ast_value);
124
+
125
+ #endif /* INTERNAL_RUBY_PARSE_H */
@@ -0,0 +1,297 @@
1
+ #ifndef INTERNAL_SANITIZERS_H /*-*-C-*-vi:se ft=c:*/
2
+ #define INTERNAL_SANITIZERS_H
3
+ /**
4
+ * @author Ruby developers <ruby-core@ruby-lang.org>
5
+ * @copyright This file is a part of the programming language Ruby.
6
+ * Permission is hereby granted, to either redistribute and/or
7
+ * modify this file, provided that the conditions mentioned in the
8
+ * file COPYING are met. Consult the file for details.
9
+ * @brief Internal header for ASAN / MSAN / etc.
10
+ */
11
+ #include "ruby/internal/config.h"
12
+ #include "internal/compilers.h" /* for __has_feature */
13
+
14
+ #ifdef HAVE_VALGRIND_MEMCHECK_H
15
+ # include <valgrind/memcheck.h>
16
+ #endif
17
+
18
+ #ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
19
+ # if __has_feature(address_sanitizer)
20
+ # define RUBY_ASAN_ENABLED
21
+ # include <sanitizer/asan_interface.h>
22
+ # endif
23
+ #endif
24
+
25
+ #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
26
+ # if __has_feature(memory_sanitizer)
27
+ # define RUBY_MSAN_ENABLED
28
+ # include <sanitizer/msan_interface.h>
29
+ # endif
30
+ #endif
31
+
32
+ #include "ruby/internal/stdbool.h" /* for bool */
33
+ #include "ruby/ruby.h" /* for VALUE */
34
+
35
+ #if 0
36
+ #elif defined(RUBY_ASAN_ENABLED) && defined(RUBY_MSAN_ENABLED)
37
+ # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
38
+ __attribute__((__no_sanitize__("memory, address"), __noinline__)) x
39
+ #elif defined(RUBY_ASAN_ENABLED)
40
+ # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
41
+ __attribute__((__no_sanitize__("address"), __noinline__)) x
42
+ #elif defined(NO_SANITIZE_ADDRESS)
43
+ # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
44
+ NO_SANITIZE_ADDRESS(NOINLINE(x))
45
+ #elif defined(NO_ADDRESS_SAFETY_ANALYSIS)
46
+ # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
47
+ NO_ADDRESS_SAFETY_ANALYSIS(NOINLINE(x))
48
+ #else
49
+ # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) x
50
+ #endif
51
+
52
+ #if defined(NO_SANITIZE) && RBIMPL_COMPILER_IS(GCC)
53
+ /* GCC warns about unknown sanitizer, which is annoying. */
54
+ # include "internal/warnings.h"
55
+ # undef NO_SANITIZE
56
+ # define NO_SANITIZE(x, y) \
57
+ COMPILER_WARNING_PUSH; \
58
+ COMPILER_WARNING_IGNORED(-Wattributes); \
59
+ __attribute__((__no_sanitize__(x))) y; \
60
+ COMPILER_WARNING_POP
61
+ #endif
62
+
63
+ #ifndef NO_SANITIZE
64
+ # define NO_SANITIZE(x, y) y
65
+ #endif
66
+
67
+ #ifndef RUBY_ASAN_ENABLED
68
+ # define __asan_poison_memory_region(x, y)
69
+ # define __asan_unpoison_memory_region(x, y)
70
+ # define __asan_region_is_poisoned(x, y) 0
71
+ # define __asan_get_current_fake_stack() NULL
72
+ # define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL
73
+ #endif
74
+
75
+ #ifndef RUBY_MSAN_ENABLED
76
+ # define __msan_allocated_memory(x, y) ((void)(x), (void)(y))
77
+ # define __msan_poison(x, y) ((void)(x), (void)(y))
78
+ # define __msan_unpoison(x, y) ((void)(x), (void)(y))
79
+ # define __msan_unpoison_string(x) ((void)(x))
80
+ #endif
81
+
82
+ #ifdef VALGRIND_MAKE_READABLE
83
+ # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
84
+ #endif
85
+
86
+ #ifdef VALGRIND_MAKE_WRITABLE
87
+ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
88
+ #endif
89
+
90
+ #ifndef VALGRIND_MAKE_MEM_DEFINED
91
+ # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
92
+ #endif
93
+
94
+ #ifndef VALGRIND_MAKE_MEM_UNDEFINED
95
+ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
96
+ #endif
97
+
98
+ /**
99
+ * This function asserts that a (continuous) memory region from ptr to size
100
+ * being "poisoned". Both read / write access to such memory region are
101
+ * prohibited until properly unpoisoned. The region must be previously
102
+ * allocated (do not pass a freed pointer here), but not necessarily be an
103
+ * entire object that the malloc returns. You can punch hole a part of a
104
+ * gigantic heap arena. This is handy when you do not free an allocated memory
105
+ * region to reuse later: poison when you keep it unused, and unpoison when you
106
+ * reuse.
107
+ *
108
+ * @param[in] ptr pointer to the beginning of the memory region to poison.
109
+ * @param[in] size the length of the memory region to poison.
110
+ */
111
+ static inline void
112
+ asan_poison_memory_region(const volatile void *ptr, size_t size)
113
+ {
114
+ __msan_poison(ptr, size);
115
+ __asan_poison_memory_region(ptr, size);
116
+ }
117
+
118
+ /**
119
+ * This is a variant of asan_poison_memory_region that takes a VALUE.
120
+ *
121
+ * @param[in] obj target object.
122
+ */
123
+ static inline void
124
+ asan_poison_object(VALUE obj)
125
+ {
126
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
127
+ asan_poison_memory_region(ptr, SIZEOF_VALUE);
128
+ }
129
+
130
+ #ifdef RUBY_ASAN_ENABLED
131
+ #define asan_poison_object_if(ptr, obj) do { \
132
+ if (ptr) asan_poison_object(obj); \
133
+ } while (0)
134
+ #else
135
+ #define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
136
+ #endif
137
+
138
+ /**
139
+ * This function predicates if the given object is fully addressable or not.
140
+ *
141
+ * @param[in] obj target object.
142
+ * @retval 0 the given object is fully addressable.
143
+ * @retval otherwise pointer to first such byte who is poisoned.
144
+ */
145
+ static inline void *
146
+ asan_poisoned_object_p(VALUE obj)
147
+ {
148
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
149
+ return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
150
+ }
151
+
152
+ /**
153
+ * This function asserts that a (formally poisoned) memory region from ptr to
154
+ * size is now addressable. Write access to such memory region gets allowed.
155
+ * However read access might or might not be possible depending on situations,
156
+ * because the region can have contents of previous usages. That information
157
+ * should be passed by the malloc_p flag. If that is true, the contents of the
158
+ * region is _not_ fully defined (like the return value of malloc behaves).
159
+ * Reading from there is NG; write something first. If malloc_p is false on
160
+ * the other hand, that memory region is fully defined and can be read
161
+ * immediately.
162
+ *
163
+ * @param[in] ptr pointer to the beginning of the memory region to unpoison.
164
+ * @param[in] size the length of the memory region.
165
+ * @param[in] malloc_p if the memory region is like a malloc's return value or not.
166
+ */
167
+ static inline void
168
+ asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
169
+ {
170
+ __asan_unpoison_memory_region(ptr, size);
171
+ if (malloc_p) {
172
+ __msan_allocated_memory(ptr, size);
173
+ }
174
+ else {
175
+ __msan_unpoison(ptr, size);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * This is a variant of asan_unpoison_memory_region that takes a VALUE.
181
+ *
182
+ * @param[in] obj target object.
183
+ * @param[in] malloc_p if the memory region is like a malloc's return value or not.
184
+ */
185
+ static inline void
186
+ asan_unpoison_object(VALUE obj, bool newobj_p)
187
+ {
188
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
189
+ asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
190
+ }
191
+
192
+ static inline void *
193
+ asan_unpoison_object_temporary(VALUE obj)
194
+ {
195
+ void *ptr = asan_poisoned_object_p(obj);
196
+ asan_unpoison_object(obj, false);
197
+ return ptr;
198
+ }
199
+
200
+ static inline void *
201
+ asan_poison_object_restore(VALUE obj, void *ptr)
202
+ {
203
+ if (ptr) {
204
+ asan_poison_object(obj);
205
+ }
206
+ return NULL;
207
+ }
208
+
209
+
210
+ /**
211
+ * Checks if the given pointer is on an ASAN fake stack. If so, it returns the
212
+ * address this variable has on the real frame; if not, it returns the origin
213
+ * address unmodified.
214
+ *
215
+ * n.b. - _dereferencing_ the returned address is meaningless and should not
216
+ * be done; even though ASAN reserves space for the variable in both the real and
217
+ * fake stacks, the _value_ of that variable is only in the fake stack.
218
+ *
219
+ * n.b. - this only works for addresses passed in from local variables on the same
220
+ * thread, because the ASAN fake stacks are threadlocal.
221
+ *
222
+ * @param[in] slot the address of some local variable
223
+ * @retval a pointer to something from that frame on the _real_ machine stack
224
+ */
225
+ static inline void *
226
+ asan_get_real_stack_addr(void* slot)
227
+ {
228
+ VALUE *addr;
229
+ addr = __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), slot, NULL, NULL);
230
+ return addr ? addr : slot;
231
+ }
232
+
233
+ /**
234
+ * Gets the current thread's fake stack handle, which can be passed into get_fake_stack_extents
235
+ *
236
+ * @retval An opaque value which can be passed to asan_get_fake_stack_extents
237
+ */
238
+ static inline void *
239
+ asan_get_thread_fake_stack_handle(void)
240
+ {
241
+ return __asan_get_current_fake_stack();
242
+ }
243
+
244
+ /**
245
+ * Checks if the given VALUE _actually_ represents a pointer to an ASAN fake stack.
246
+ *
247
+ * If the given slot _is_ actually a reference to an ASAN fake stack, and that fake stack
248
+ * contains the real values for the passed-in range of machine stack addresses, returns true
249
+ * and the range of the fake stack through the outparams.
250
+ *
251
+ * Otherwise, returns false, and sets the outparams to NULL.
252
+ *
253
+ * Note that this function expects "start" to be > "end" on downward-growing stack architectures;
254
+ *
255
+ * @param[in] thread_fake_stack_handle The asan fake stack reference for the thread we're scanning
256
+ * @param[in] slot The value on the machine stack we want to inspect
257
+ * @param[in] machine_stack_start The extents of the real machine stack on which slot lives
258
+ * @param[in] machine_stack_end The extents of the real machine stack on which slot lives
259
+ * @param[out] fake_stack_start_out The extents of the fake stack which contains real VALUEs
260
+ * @param[out] fake_stack_end_out The extents of the fake stack which contains real VALUEs
261
+ * @return Whether slot is a pointer to a fake stack for the given machine stack range
262
+ */
263
+
264
+ static inline bool
265
+ asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot,
266
+ void *machine_stack_start, void *machine_stack_end,
267
+ void **fake_stack_start_out, void **fake_stack_end_out)
268
+ {
269
+ /* the ifdef is needed here to suppress a warning about fake_frame_{start/end} being
270
+ uninitialized if __asan_addr_is_in_fake_stack is an empty macro */
271
+ #ifdef RUBY_ASAN_ENABLED
272
+ void *fake_frame_start;
273
+ void *fake_frame_end;
274
+ void *real_stack_frame = __asan_addr_is_in_fake_stack(
275
+ thread_fake_stack_handle, (void *)slot, &fake_frame_start, &fake_frame_end
276
+ );
277
+ if (real_stack_frame) {
278
+ bool in_range;
279
+ #if STACK_GROW_DIRECTION < 0
280
+ in_range = machine_stack_start >= real_stack_frame && real_stack_frame >= machine_stack_end;
281
+ #else
282
+ in_range = machine_stack_start <= real_stack_frame && real_stack_frame <= machine_stack_end;
283
+ #endif
284
+ if (in_range) {
285
+ *fake_stack_start_out = fake_frame_start;
286
+ *fake_stack_end_out = fake_frame_end;
287
+ return true;
288
+ }
289
+ }
290
+ #endif
291
+ *fake_stack_start_out = 0;
292
+ *fake_stack_end_out = 0;
293
+ return false;
294
+ }
295
+
296
+
297
+ #endif /* INTERNAL_SANITIZERS_H */
@@ -0,0 +1,23 @@
1
+ #ifndef INTERNAL_SERIAL_H /*-*-C-*-vi:se ft=c:*/
2
+ #define INTERNAL_SERIAL_H
3
+ /**
4
+ * @author Ruby developers <ruby-core@ruby-lang.org>
5
+ * @copyright This file is a part of the programming language Ruby.
6
+ * Permission is hereby granted, to either redistribute and/or
7
+ * modify this file, provided that the conditions mentioned in the
8
+ * file COPYING are met. Consult the file for details.
9
+ * @brief Internal header for rb_serial_t.
10
+ */
11
+ #include "ruby/internal/config.h" /* for HAVE_LONG_LONG */
12
+ #include "ruby/defines.h" /* for LONG_LONG */
13
+
14
+ #ifndef HAVE_LONG_LONG
15
+ # error need C99+
16
+ #endif
17
+
18
+ typedef unsigned LONG_LONG rb_serial_t;
19
+ #define SERIALT2NUM ULL2NUM
20
+ #define PRI_SERIALT_PREFIX PRI_LL_PREFIX
21
+ #define SIZEOF_SERIAL_T SIZEOF_LONG_LONG
22
+
23
+ #endif /* INTERNAL_SERIAL_H */
@@ -0,0 +1,16 @@
1
+ #ifndef INTERNAL_STATIC_ASSERT_H /*-*-C-*-vi:se ft=c:*/
2
+ #define INTERNAL_STATIC_ASSERT_H
3
+ /**
4
+ * @author Ruby developers <ruby-core@ruby-lang.org>
5
+ * @copyright This file is a part of the programming language Ruby.
6
+ * Permission is hereby granted, to either redistribute and/or
7
+ * modify this file, provided that the conditions mentioned in the
8
+ * file COPYING are met. Consult the file for details.
9
+ * @brief C11 shim for _Static_assert.
10
+ */
11
+ #include "ruby/internal/static_assert.h"
12
+ #ifndef STATIC_ASSERT
13
+ # define STATIC_ASSERT RBIMPL_STATIC_ASSERT
14
+ #endif
15
+
16
+ #endif /* INTERNAL_STATIC_ASSERT_H */