diff options
| -rw-r--r-- | include/mruby.h | 1 | ||||
| -rw-r--r-- | include/mruby/value.h | 2 | ||||
| -rw-r--r-- | src/symbol.c | 22 |
3 files changed, 24 insertions, 1 deletions
diff --git a/include/mruby.h b/include/mruby.h index 480080e8b..c45925844 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -161,6 +161,7 @@ typedef struct mrb_state { mrb_bool gc_full:1; mrb_bool is_generational_gc_mode:1; mrb_bool out_of_memory:1; + mrb_bool symbol_table_overflow:1; size_t majorgc_old_threshold; struct alloca_header *mems; diff --git a/include/mruby/value.h b/include/mruby/value.h index b1278e3a3..859687ffc 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -7,7 +7,7 @@ #ifndef MRUBY_VALUE_H #define MRUBY_VALUE_H -typedef short mrb_sym; +typedef uint16_t mrb_sym; typedef uint8_t mrb_bool; struct mrb_state; diff --git a/src/symbol.c b/src/symbol.c index 1736a12b7..7fcef2817 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -5,6 +5,7 @@ */ #include <ctype.h> +#include <limits.h> #include <string.h> #include "mruby.h" #include "mruby/khash.h" @@ -44,6 +45,14 @@ sym_validate_len(mrb_state *mrb, size_t len) } } +#define MRB_SYM_MAX UINT16_MAX + +static mrb_value +sym_tbl_overflow_new_str(mrb_state *mrb, const char *name, size_t len) +{ + return mrb_str_inspect(mrb, mrb_str_new(mrb, name, len)); +} + static mrb_sym sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) { @@ -61,6 +70,19 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) if (k != kh_end(h)) return kh_value(h, k); + if (mrb->symbol_table_overflow) { + if (mrb->symidx == MRB_SYM_MAX) { + mrb_bug(mrb, "symbol table overflow (symbol %S)", sym_tbl_overflow_new_str(mrb, name, len)); + } + } + else { + if (mrb->symidx >= MRB_SYM_MAX - 8) { /* raising might intern a few new strings */ + mrb->symbol_table_overflow = TRUE; + mrb_raisef(mrb, E_RUNTIME_ERROR, "symbol table overflow (symbol %S)", + sym_tbl_overflow_new_str(mrb, name, len)); + } + } + sym = ++mrb->symidx; if (lit) { sname.name = name; |
