summaryrefslogtreecommitdiffhomepage
path: root/src/symbol.c
diff options
context:
space:
mode:
authorcremno <[email protected]>2014-08-27 12:51:10 +0200
committercremno <[email protected]>2014-08-27 12:51:10 +0200
commit89b27648dd2cc05ea60bb6c79aec4db1ef712497 (patch)
tree7f4a15c95d03702d9e8a4c1cff6b3bea135b29e4 /src/symbol.c
parentecda19f4024cd853d933b059ba9f082a42837096 (diff)
downloadmruby-89b27648dd2cc05ea60bb6c79aec4db1ef712497.tar.gz
mruby-89b27648dd2cc05ea60bb6c79aec4db1ef712497.zip
add symbol table overflow check
Since raising an error might intern a few new strings, some symbols need to be reserved. 8 should be sufficient. If the real limit has been reached, mrb_bug() is called.
Diffstat (limited to 'src/symbol.c')
-rw-r--r--src/symbol.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/symbol.c b/src/symbol.c
index 69f9c90ee..5e40fa315 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"
@@ -34,6 +35,15 @@ sym_hash_func(mrb_state *mrb, const symbol_name s)
KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE)
KHASH_DEFINE (n2s, symbol_name, mrb_sym, TRUE, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */
+
+#define MRB_SYM_MAX SHRT_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)
{
@@ -53,6 +63,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;