diff options
35 files changed, 571 insertions, 271 deletions
@@ -28,6 +28,20 @@ send a detailed report to the developers that includes the error log, machine, and OS type. +* Adding existing gems + +Gems from the [list of mruby gems](http://www.mruby.org/libraries/) can be added by adding +their respective GitHub URLs to build_config.rb. For example, to add implementations of the +File and IO Ruby core classes to mruby, insert the following in build_config.rb under the +comment section `Use mrbgems`: + + conf.gem :git => '[email protected]:iij/mruby-io.git', :branch => 'master' + + Afterwards, re-run: + + ruby ./minirake + + * Porting to other platforms @@ -41,7 +41,7 @@ The URL of the mruby home-page is: To subscribe to the mruby mailing list....[T.B.D.] -## How to compile and install +## How to compile and install (mruby and gems) See the INSTALL file. diff --git a/include/mruby/debug.h b/include/mruby/debug.h index 2e358a4ca..a56321d42 100644 --- a/include/mruby/debug.h +++ b/include/mruby/debug.h @@ -28,10 +28,10 @@ typedef struct mrb_irep_debug_info_file { uint32_t line_entry_count; mrb_debug_line_type line_type; union { - void *line_ptr; - mrb_irep_debug_info_line *line_flat_map; - uint16_t *line_ary; - }; + void *ptr; + mrb_irep_debug_info_line *flat_map; + uint16_t *ary; + } lines; } mrb_irep_debug_info_file; typedef struct mrb_irep_debug_info { diff --git a/include/mruby/dump.h b/include/mruby/dump.h index 69fd776b3..35546f9de 100644 --- a/include/mruby/dump.h +++ b/include/mruby/dump.h @@ -92,14 +92,14 @@ struct rite_binary_footer { RITE_SECTION_HEADER; }; -static inline int +static inline size_t uint8_to_bin(uint8_t s, uint8_t *bin) { *bin = s; return sizeof(uint8_t); } -static inline int +static inline size_t uint16_to_bin(uint16_t s, uint8_t *bin) { *bin++ = (s >> 8) & 0xff; @@ -107,7 +107,7 @@ uint16_to_bin(uint16_t s, uint8_t *bin) return sizeof(uint16_t); } -static inline int +static inline size_t uint32_to_bin(uint32_t l, uint8_t *bin) { *bin++ = (l >> 24) & 0xff; diff --git a/include/mruby/string.h b/include/mruby/string.h index 7e7fb13d9..31e101246 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -15,14 +15,7 @@ extern "C" { extern const char mrb_digitmap[]; -/* (sizeof(mrb_int)*2+sizeof(char*))/sizeof(char)-1 */ -#if defined(MRB_INT16) -# define RSTRING_EMBED_LEN_MAX 9 -#elif defined(MRB_INT64) -# define RSTRING_EMBED_LEN_MAX 15 -#else -# define RSTRING_EMBED_LEN_MAX 11 -#endif +#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1)) struct RString { MRB_OBJECT_HEADER; @@ -54,11 +47,12 @@ struct RString { RSTRING_EMBED_LEN_MAX :\ RSTRING(s)->as.heap.aux.capa) #define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) +mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 #define MRB_STR_EMBED 4 -#define MRB_STR_EMBED_LEN_MASK 120 +#define MRB_STR_EMBED_LEN_MASK 0xf8 #define MRB_STR_EMBED_LEN_SHIFT 3 void mrb_gc_free_str(mrb_state*, struct RString*); diff --git a/include/mruby/value.h b/include/mruby/value.h index d51fbb7bc..a940aabb7 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -72,6 +72,8 @@ typedef short mrb_sym; # define PRIo64 "I64o" # define PRIx64 "I64x" # define PRIX64 "I64X" +# define INFINITY ((float)(DBL_MAX * DBL_MAX)) +# define NAN ((float)(INFINITY - INFINITY)) # else # include <inttypes.h> # endif diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index a42577a57..320bc30fb 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -15,15 +15,29 @@ #include "mruby/string.h" #ifdef ENABLE_READLINE -#include <limits.h> #include <readline/readline.h> #include <readline/history.h> - +#define MIRB_ADD_HISTORY(line) add_history(line) +#define MIRB_READLINE(ch) readline(ch) +#define MIRB_WRITE_HISTORY(path) write_history(path) +#define MIRB_READ_HISTORY(path) read_history(path) +#define MIRB_USING_HISTORY() using_history() +#elif ENABLE_LINENOISE +#define ENABLE_READLINE +#include <linenoise.h> +#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line) +#define MIRB_READLINE(ch) linenoise(ch) +#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path) +#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path) +#define MIRB_USING_HISTORY() +#endif + +#ifdef ENABLE_READLINE +#include <limits.h> static const char *history_file_name = ".mirb_history"; char history_path[PATH_MAX]; #endif - static void p(mrb_state *mrb, mrb_value obj, int prompt) { @@ -281,7 +295,7 @@ main(int argc, char **argv) ai = mrb_gc_arena_save(mrb); #ifdef ENABLE_READLINE - using_history(); + MIRB_USING_HISTORY(); home = getenv("HOME"); #ifdef _WIN32 if (!home) @@ -291,7 +305,7 @@ main(int argc, char **argv) strcpy(history_path, home); strcat(history_path, "/"); strcat(history_path, history_file_name); - read_history(history_path); + MIRB_READ_HISTORY(history_path); } #endif @@ -312,13 +326,13 @@ main(int argc, char **argv) last_code_line[char_index] = '\0'; #else - char* line = readline(code_block_open ? "* " : "> "); + char* line = MIRB_READLINE(code_block_open ? "* " : "> "); if (line == NULL) { printf("\n"); break; } strncpy(last_code_line, line, sizeof(last_code_line)-1); - add_history(line); + MIRB_ADD_HISTORY(line); free(line); #endif @@ -387,7 +401,7 @@ main(int argc, char **argv) mrb_close(mrb); #ifdef ENABLE_READLINE - write_history(history_path); + MIRB_WRITE_HISTORY(history_path); #endif return 0; diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c index 92bf15c5f..01e38ef84 100644 --- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c @@ -193,7 +193,7 @@ main(int argc, char **argv) ARGV = mrb_ary_new_capa(mrb, args.argc); for (i = 0; i < args.argc; i++) { - mrb_ary_push(mrb, ARGV, mrb_str_new(mrb, args.argv[i], strlen(args.argv[i]))); + mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, args.argv[i])); } mrb_define_global_const(mrb, "ARGV", ARGV); diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index 0bf1204f5..4e41891a4 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -21,7 +21,7 @@ mrb_proc_source_location(mrb_state *mrb, mrb_value self) } else { mrb_irep *irep = p->body.irep; - uint32_t line; + int32_t line; const char *filename; filename = mrb_debug_get_filename(irep, 0); diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c index 3de935232..a27aee311 100644 --- a/mrbgems/mruby-random/src/mt19937ar.c +++ b/mrbgems/mruby-random/src/mt19937ar.c @@ -63,7 +63,7 @@ unsigned long mrb_random_genrand_int32(mt_state *t) y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); - t->gen_int = y; + t->gen.int_ = y; return y; } @@ -71,8 +71,8 @@ unsigned long mrb_random_genrand_int32(mt_state *t) double mrb_random_genrand_real1(mt_state *t) { mrb_random_genrand_int32(t); - t->gen_dbl = t->gen_int*(1.0/4294967295.0); - return t->gen_dbl; + t->gen.double_ = t->gen.int_*(1.0/4294967295.0); + return t->gen.double_; /* divided by 2^32-1 */ } diff --git a/mrbgems/mruby-random/src/mt19937ar.h b/mrbgems/mruby-random/src/mt19937ar.h index 504355193..59027c624 100644 --- a/mrbgems/mruby-random/src/mt19937ar.h +++ b/mrbgems/mruby-random/src/mt19937ar.h @@ -10,12 +10,12 @@ typedef struct { unsigned long mt[N]; int mti; union { - unsigned long gen_int; - double gen_dbl; - }; + unsigned long int_; + double double_; + } gen; mrb_int seed; - mrb_bool has_seed; + mrb_bool has_seed : 1; } mt_state; void mrb_random_init_genrand(mt_state *, unsigned long); diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 4ef009c54..8f983ea0f 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -90,21 +90,31 @@ get_opt(mrb_state* mrb) return arg; } +static mrb_value +get_random(mrb_state *mrb) { + return mrb_const_get(mrb, + mrb_obj_value(mrb_class_get(mrb, "Random")), + mrb_intern_lit(mrb, "DEFAULT")); +} + +static mt_state * +get_random_state(mrb_state *mrb) +{ + mrb_value random_val = get_random(mrb); + return DATA_GET_PTR(mrb, random_val, &mt_state_type, mt_state); +} + static mrb_value mrb_random_g_rand(mrb_state *mrb, mrb_value self) { - mrb_value random = mrb_const_get(mrb, - mrb_obj_value(mrb_class_get(mrb, "Random")), - mrb_intern_lit(mrb, "DEFAULT")); + mrb_value random = get_random(mrb); return mrb_random_rand(mrb, random); } static mrb_value mrb_random_g_srand(mrb_state *mrb, mrb_value self) { - mrb_value random = mrb_const_get(mrb, - mrb_obj_value(mrb_class_get(mrb, "Random")), - mrb_intern_lit(mrb, "DEFAULT")); + mrb_value random = get_random(mrb); return mrb_random_srand(mrb, random); } @@ -154,7 +164,7 @@ static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self) { mrb_value max; - mt_state *t = DATA_PTR(self); + mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); max = get_opt(mrb); mrb_random_rand_seed(mrb, t); @@ -166,7 +176,7 @@ mrb_random_srand(mrb_state *mrb, mrb_value self) { mrb_value seed; mrb_value old_seed; - mt_state *t = DATA_PTR(self); + mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); seed = get_opt(mrb); seed = mrb_random_mt_srand(mrb, t, seed); @@ -200,10 +210,7 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) mrb_get_args(mrb, "|d", &random, &mt_state_type); if (random == NULL) { - mrb_value random_val = mrb_const_get(mrb, - mrb_obj_value(mrb_class_get(mrb, "Random")), - mrb_intern_lit(mrb, "DEFAULT")); - random = (mt_state *)DATA_PTR(random_val); + random = get_random_state(mrb); } mrb_random_rand_seed(mrb, random); @@ -240,6 +247,77 @@ mrb_ary_shuffle(mrb_state *mrb, mrb_value ary) return new_ary; } +/* + * call-seq: + * ary.sample -> obj + * ary.sample(n) -> new_ary + * + * Choose a random element or +n+ random elements from the array. + * + * The elements are chosen by using random and unique indices into the array + * in order to ensure that an element doesn't repeat itself unless the array + * already contained duplicate elements. + * + * If the array is empty the first form returns +nil+ and the second form + * returns an empty array. + */ + +static mrb_value +mrb_ary_sample(mrb_state *mrb, mrb_value ary) +{ + mrb_int n = 0; + mrb_bool given; + mt_state *random = NULL; + mrb_int len = RARRAY_LEN(ary); + + mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type); + if (random == NULL) { + random = get_random_state(mrb); + } + mrb_random_rand_seed(mrb, random); + mt_rand(random); + if (!given) { /* pick one element */ + switch (len) { + case 0: + return mrb_nil_value(); + case 1: + return RARRAY_PTR(ary)[0]; + default: + return RARRAY_PTR(ary)[mt_rand(random) % len]; + } + } + else { + mrb_value result; + mrb_int i, j; + + if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number"); + if (n > len) n = len; + result = mrb_ary_new_capa(mrb, n); + for (i=0; i<n; i++) { + mrb_int r; + + for (;;) { + retry: + r = mt_rand(random) % len; + + for (j=0; j<i; j++) { + if (mrb_fixnum(RARRAY_PTR(result)[j]) == r) { + goto retry; /* retry if duplicate */ + } + } + break; + } + RARRAY_PTR(result)[i] = mrb_fixnum_value(r); + RARRAY_LEN(result)++; + } + for (i=0; i<n; i++) { + RARRAY_PTR(result)[i] = RARRAY_PTR(ary)[mrb_fixnum(RARRAY_PTR(result)[i])]; + } + return result; + } +} + + void mrb_mruby_random_gem_init(mrb_state *mrb) { struct RClass *random; @@ -259,6 +337,7 @@ void mrb_mruby_random_gem_init(mrb_state *mrb) mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1)); mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, array, "sample", mrb_ary_sample, MRB_ARGS_OPT(2)); mrb_const_set(mrb, mrb_obj_value(random), mrb_intern_lit(mrb, "DEFAULT"), mrb_obj_new(mrb, random, 0, NULL)); diff --git a/mrbgems/mruby-random/test/random.rb b/mrbgems/mruby-random/test/random.rb index c4e4082ad..fa31b782b 100644 --- a/mrbgems/mruby-random/test/random.rb +++ b/mrbgems/mruby-random/test/random.rb @@ -73,4 +73,4 @@ assert('Array#shuffle!(random)') do ary2.shuffle! Random.new 345 ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2 -end
\ No newline at end of file +end diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 02b842e53..646414f0c 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -381,7 +381,7 @@ mrb_struct_s_def(mrb_state *mrb, mrb_value klass) } st = make_struct(mrb, name, rest, struct_class(mrb)); if (!mrb_nil_p(b)) { - mrb_funcall(mrb, b, "call", 1, &st); + mrb_funcall(mrb, b, "call", 1, st); } return st; diff --git a/src/class.c b/src/class.c index 9880a82fa..72e96ece8 100644 --- a/src/class.c +++ b/src/class.c @@ -411,6 +411,7 @@ to_hash(mrb_state *mrb, mrb_value val) &: Block [mrb_value] *: rest argument [mrb_value*,int] Receive the rest of the arguments as an array. |: optional Next argument of '|' and later are optional. + ?: optional given [mrb_bool] true if preceding argument (optional) is given. */ int mrb_get_args(mrb_state *mrb, const char *format, ...) @@ -420,7 +421,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *sp = mrb->c->stack + 1; va_list ap; int argc = mrb->c->ci->argc; - int opt = 0; + mrb_bool opt = 0; + mrb_bool given = 1; va_start(ap, format); if (argc < 0) { @@ -431,11 +433,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } while ((c = *format++)) { switch (c) { - case '|': case '*': case '&': + case '|': case '*': case '&': case '?': break; default: - if (argc <= i && !opt) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + if (argc <= i) { + if (opt) { + given = 0; + } + else { + mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + } } break; } @@ -527,22 +534,12 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case 'z': { mrb_value ss; - struct RString *s; char **ps; - mrb_int len; ps = va_arg(ap, char**); if (i < argc) { ss = to_str(mrb, *sp++); - s = mrb_str_ptr(ss); - len = (mrb_int)strlen(RSTRING_PTR(ss)); - if (len < RSTRING_LEN(ss)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); - } - else if (len > RSTRING_LEN(ss)) { - mrb_str_modify(mrb, s); - } - *ps = RSTRING_PTR(ss); + *ps = mrb_string_value_cstr(mrb, &ss); i++; } } @@ -689,6 +686,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case '|': opt = 1; break; + case '?': + { + mrb_bool *p; + + p = va_arg(ap, mrb_bool*); + *p = given; + } + break; case '*': { diff --git a/src/codegen.c b/src/codegen.c index 0b4d18bba..b0d7454dc 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -5,6 +5,7 @@ */ #include <ctype.h> +#include <limits.h> #include <stdlib.h> #include <string.h> #include "mruby.h" @@ -1914,7 +1915,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_value fix = mrb_fixnum_value((intptr_t)tree); mrb_value str = mrb_str_buf_new(mrb, 4); - mrb_str_buf_cat(mrb, str, "$", 1); + mrb_str_cat_lit(mrb, str, "$"); mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10)); sym = new_sym(s, mrb_intern_str(mrb, str)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); @@ -2106,7 +2107,7 @@ codegen(codegen_scope *s, node *tree, int val) char *p2 = (char*)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); - int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); + int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); int argc = 1; genop(s, MKOP_A(OP_OCLASS, cursp())); @@ -2115,7 +2116,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_ABx(OP_STRING, cursp(), off)); if (p2) { push(); - off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2))); + off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); argc++; pop(); @@ -2152,7 +2153,7 @@ codegen(codegen_scope *s, node *tree, int val) n = tree->cdr->cdr; if (n->car) { p = (char*)n->car; - off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p))); + off = new_lit(s, mrb_str_new_cstr(s->mrb, p)); codegen(s, tree->car, VAL); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); pop(); @@ -2163,7 +2164,7 @@ codegen(codegen_scope *s, node *tree, int val) int off; push(); - off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2))); + off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); argc++; pop(); @@ -2582,14 +2583,16 @@ static void codedump(mrb_state *mrb, mrb_irep *irep) { #ifdef ENABLE_STDIO - uint32_t i; + int i; int ai; mrb_code c; if (!irep) return; printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", irep, irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen); - for (i=0; i<irep->ilen; i++) { + + mrb_assert(irep->ilen <= INT_MAX); + for (i = 0; i < (int)(irep->ilen); i++) { ai = mrb_gc_arena_save(mrb); printf("%03d ", i); c = irep->iseq[i]; diff --git a/src/debug.c b/src/debug.c index cdb0aa9e8..1a3dc275d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -74,11 +74,11 @@ mrb_debug_get_line(mrb_irep *irep, uint32_t pc) switch(f->line_type) { case mrb_debug_line_ary: mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count)); - return f->line_ary[pc - f->start_pos]; + return f->lines.ary[pc - f->start_pos]; case mrb_debug_line_flat_map: { /* get upper bound */ - mrb_irep_debug_info_line *ret = f->line_flat_map; + mrb_irep_debug_info_line *ret = f->lines.flat_map; uint32_t count = f->line_entry_count; while (count > 0) { int32_t step = count / 2; @@ -92,10 +92,10 @@ mrb_debug_get_line(mrb_irep *irep, uint32_t pc) --ret; /* check line entry pointer range */ - mrb_assert(f->line_flat_map <= ret && ret < (f->line_flat_map + f->line_entry_count)); + mrb_assert(f->lines.flat_map <= ret && ret < (f->lines.flat_map + f->line_entry_count)); /* check pc range */ mrb_assert(ret->start_pos <= pc && - pc < (((ret + 1 - f->line_flat_map) < f->line_entry_count) + pc < (((ret + 1 - f->lines.flat_map) < f->line_entry_count) ? (ret+1)->start_pos : irep->debug_info->pc_count)); return ret->line; @@ -160,31 +160,31 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos); - ret->line_ptr = NULL; + ret->lines.ptr = NULL; switch(ret->line_type) { case mrb_debug_line_ary: ret->line_entry_count = file_pc_count; - ret->line_ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); + ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); for(i = 0; i < file_pc_count; ++i) { - ret->line_ary[i] = irep->lines[start_pos + i]; + ret->lines.ary[i] = irep->lines[start_pos + i]; } break; case mrb_debug_line_flat_map: { uint16_t prev_line = 0; mrb_irep_debug_info_line m; - ret->line_flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); + ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); ret->line_entry_count = 0; for(i = 0; i < file_pc_count; ++i) { if(irep->lines[start_pos + i] == prev_line) { continue; } - ret->line_flat_map = (mrb_irep_debug_info_line*)mrb_realloc( - mrb, ret->line_flat_map, + ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc( + mrb, ret->lines.flat_map, sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1)); m.start_pos = start_pos + i; m.line = irep->lines[start_pos + i]; - ret->line_flat_map[ret->line_entry_count] = m; + ret->lines.flat_map[ret->line_entry_count] = m; /* update */ ++ret->line_entry_count; @@ -207,7 +207,7 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d) for(i = 0; i < d->flen; ++i) { mrb_assert(d->files[i]); - mrb_free(mrb, d->files[i]->line_ptr); + mrb_free(mrb, d->files[i]->lines.ptr); mrb_free(mrb, d->files[i]); } mrb_free(mrb, d->files); diff --git a/src/dump.c b/src/dump.c index 4c843f8d7..393918b45 100644 --- a/src/dump.c +++ b/src/dump.c @@ -12,12 +12,16 @@ #include "mruby/numeric.h" #include "mruby/debug.h" -static uint32_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); +static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); -static uint32_t +#if UINT32_MAX > SIZE_MAX +# error This code cannot be built on your environment. +#endif + +static size_t get_irep_header_size(mrb_state *mrb) { - uint32_t size = 0; + size_t size = 0; size += sizeof(uint32_t) * 1; size += sizeof(uint16_t) * 3; @@ -25,7 +29,7 @@ get_irep_header_size(mrb_state *mrb) return size; } -static uint32_t +static ptrdiff_t write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; @@ -35,20 +39,22 @@ write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */ cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */ - return (cur - buf); + return cur - buf; } -static uint32_t +static size_t get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; + size += sizeof(uint32_t); /* ilen */ size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ + return size; } -static uint32_t +static ptrdiff_t write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; @@ -59,16 +65,15 @@ write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */ } - return (cur - buf); + return cur - buf; } -static uint32_t +static size_t get_pool_block_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; - uint32_t pool_no; - int len; + size_t size = 0; + size_t pool_no; mrb_value str; char buf[32]; @@ -81,16 +86,31 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); - size += RSTRING_LEN(str); + { + mrb_int len = RSTRING_LEN(str); + mrb_assert(len >= 0); + mrb_assert((size_t)len <= SIZE_MAX); + size += (size_t)len; + } break; case MRB_TT_FLOAT: - len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); - size += len; + { + int len; + len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); + mrb_assert(len >= 0); + mrb_assert((size_t)len <= SIZE_MAX); + size += (size_t)len; + } break; case MRB_TT_STRING: - size += RSTRING_LEN(irep->pool[pool_no]); + { + mrb_int len = RSTRING_LEN(irep->pool[pool_no]); + mrb_assert(len >= 0); + mrb_assert((size_t)len <= SIZE_MAX); + size += (size_t)len; + } break; default: @@ -102,12 +122,12 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) return size; } -static uint32_t +static ptrdiff_t write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { - uint32_t pool_no; + size_t pool_no; uint8_t *cur = buf; - uint32_t len; + uint16_t len; mrb_value str; const char *char_ptr; char char_buf[30]; @@ -122,19 +142,37 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); char_ptr = RSTRING_PTR(str); - len = RSTRING_LEN(str); + { + mrb_int tlen; + tlen = RSTRING_LEN(str); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } break; case MRB_TT_FLOAT: cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ - len = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); + { + int tlen; + tlen = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } char_ptr = &char_buf[0]; break; case MRB_TT_STRING: cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ char_ptr = RSTRING_PTR(irep->pool[pool_no]); - len = RSTRING_LEN(irep->pool[pool_no]); + { + mrb_int tlen; + tlen = RSTRING_LEN(irep->pool[pool_no]); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } break; default: @@ -142,22 +180,22 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } cur += uint16_to_bin(len, cur); /* data length */ - memcpy(cur, char_ptr, len); + memcpy(cur, char_ptr, (size_t)len); cur += len; mrb_gc_arena_restore(mrb, ai); } - return (uint32_t)(cur - buf); + return cur - buf; } -static uint32_t +static size_t get_syms_block_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; uint32_t sym_no; - uint32_t len; + size_t len; size += sizeof(uint32_t); /* slen */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { @@ -171,7 +209,7 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep) return size; } -static uint32_t +static ptrdiff_t write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint32_t sym_no; @@ -182,13 +220,11 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) for (sym_no = 0; sym_no < irep->slen; sym_no++) { if (irep->syms[sym_no] != 0) { - uint32_t len; + size_t len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); - if (len > UINT16_MAX) { - return MRB_DUMP_GENERAL_FAILURE; - } + mrb_assert(len <= UINT16_MAX); cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */ memcpy(cur, name, len); /* symbol name */ cur += (uint16_t)len; @@ -199,13 +235,13 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } } - return (uint32_t)(cur - buf); + return cur - buf; } -static uint32_t +static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; size += get_irep_header_size(mrb); size += get_iseq_block_size(mrb, irep); @@ -214,11 +250,11 @@ get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) return size; } -static uint32_t +static size_t get_irep_record_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; - uint32_t irep_no; + size_t size = 0; + size_t irep_no; size = get_irep_record_size_1(mrb, irep); for (irep_no = 0; irep_no < irep->rlen; irep_no++) { @@ -228,7 +264,7 @@ get_irep_record_size(mrb_state *mrb, mrb_irep *irep) } static int -write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_record_size) +write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, size_t *irep_record_size) { uint32_t i; @@ -250,14 +286,14 @@ write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_r for (i = 0; i < irep->rlen; i++) { int result; - uint32_t rlen; + size_t rsize; - result = write_irep_record(mrb, irep->reps[i], bin, &rlen); + result = write_irep_record(mrb, irep->reps[i], bin, &rsize); if (result != MRB_DUMP_OK) { return result; } - *irep_record_size += rlen; - bin += rlen; + *irep_record_size += rsize; + bin += rsize; } return MRB_DUMP_OK; } @@ -276,12 +312,13 @@ write_footer(mrb_state *mrb, uint8_t *bin) static int -write_section_irep_header(mrb_state *mrb, uint32_t section_size, uint8_t *bin) +write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) { struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin; memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify)); - uint32_to_bin(section_size, header->section_size); + mrb_assert(section_size <= UINT32_MAX); + uint32_to_bin((uint32_t)section_size, header->section_size); memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version)); return MRB_DUMP_OK; @@ -291,7 +328,8 @@ static int write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) { int result; - uint32_t section_size = 0, rlen = 0; /* size of irep record */ + size_t section_size = 0; /* size of irep record */ + size_t rsize = 0; uint8_t *cur = bin; if (mrb == NULL || bin == NULL) { @@ -301,33 +339,32 @@ write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) cur += sizeof(struct rite_section_irep_header); section_size += sizeof(struct rite_section_irep_header); - result = write_irep_record(mrb, irep, cur, &rlen); + result = write_irep_record(mrb, irep, cur, &rsize); if (result != MRB_DUMP_OK) { return result; } - cur += rlen; - section_size += rlen; + cur += rsize; + section_size += rsize; write_section_irep_header(mrb, section_size, bin); return MRB_DUMP_OK; } static int -write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint8_t *bin) +write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin) { struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; - /* TODO */ memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify)); - uint32_to_bin(section_size, header->section_size); + uint32_to_bin((uint32_t)section_size, header->section_size); return MRB_DUMP_OK; } -static uint32_t +static size_t get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; size += sizeof(uint32_t); /* record size */ size += sizeof(uint16_t); /* filename size */ @@ -338,21 +375,27 @@ get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) if (irep->lines) { size += sizeof(uint16_t) * irep->ilen; /* lineno */ } + return size; } -static int +static size_t write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) { uint8_t *cur = bin; - uint32_t filename_len = 0, iseq_no; + size_t iseq_no; + size_t filename_len; + ptrdiff_t diff; cur += sizeof(uint32_t); /* record size */ if (irep->filename) { filename_len = strlen(irep->filename); + } else { + filename_len = 0; } - cur += uint16_to_bin(filename_len, cur); /* filename size */ + mrb_assert(filename_len <= UINT16_MAX); + cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ if (filename_len) { memcpy(cur, irep->filename, filename_len); @@ -360,7 +403,8 @@ write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) } if (irep->lines) { - cur += uint32_to_bin(irep->ilen, cur); /* niseq */ + mrb_assert(irep->ilen <= UINT32_MAX); + cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */ } @@ -369,16 +413,21 @@ write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) cur += uint32_to_bin(0, cur); /* niseq */ } - uint32_to_bin(cur - bin, bin); /* record size */ + diff = cur - bin; + mrb_assert(diff >= 0); + mrb_assert(diff <= UINT32_MAX); + + uint32_to_bin((uint32_t)diff, bin); /* record size */ - return (cur - bin); + mrb_assert((size_t)diff <= SIZE_MAX); + return (size_t)diff; } -static int +static size_t write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) { - uint32_t i; - uint32_t rlen, size = 0; + size_t i; + size_t rlen, size = 0; rlen = write_lineno_record_1(mrb, irep, bin); bin += rlen; @@ -394,7 +443,8 @@ write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) static int write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) { - uint32_t section_size = 0, rlen = 0; /* size of irep record */ + size_t section_size = 0; + size_t rlen = 0; /* size of irep record */ uint8_t *cur = bin; if (mrb == NULL || bin == NULL) { @@ -412,11 +462,12 @@ write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) return MRB_DUMP_OK; } -static uint32_t +static size_t get_debug_record_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t ret = 0, f_idx; - uint32_t i; + size_t ret = 0; + uint16_t f_idx; + size_t i; ret += sizeof(uint32_t); /* record size */ ret += sizeof(uint16_t); /* file count */ @@ -432,11 +483,11 @@ get_debug_record_size(mrb_state *mrb, mrb_irep *irep) ret += sizeof(uint8_t); /* line type */ switch(file->line_type) { case mrb_debug_line_ary: - ret += sizeof(uint16_t) * file->line_entry_count; + ret += sizeof(uint16_t) * (size_t)(file->line_entry_count); break; case mrb_debug_line_flat_map: - ret += (sizeof(uint32_t) + sizeof(uint16_t)) * file->line_entry_count; + ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count); break; default: mrb_assert(0); break; @@ -450,9 +501,9 @@ get_debug_record_size(mrb_state *mrb, mrb_irep *irep) } static int -find_filename_index(const mrb_sym *ary, uint32_t ary_len, mrb_sym s) +find_filename_index(const mrb_sym *ary, uint16_t ary_len, mrb_sym s) { - uint32_t i; + int i; for (i = 0; i < ary_len; ++i) { if (ary[i] == s) { return i; } @@ -460,13 +511,13 @@ find_filename_index(const mrb_sym *ary, uint32_t ary_len, mrb_sym s) return -1; } -static uint32_t -get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint32_t *lp) +static size_t +get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp) { mrb_sym *filenames = *fp; - uint32_t tsize = 0; + uint16_t tsize = 0; uint32_t file_i; - uint32_t size = 0; + size_t size = 0; mrb_irep_debug_info *di = irep->debug_info; if (lp == NULL) { @@ -474,8 +525,8 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint32_t * } for (file_i = 0; file_i < di->flen; ++file_i) { mrb_irep_debug_info_file *file; - uint32_t filename_len; - uint32_t i; + size_t filename_len; + size_t i; file = di->files[file_i]; if (find_filename_index(filenames, *lp, file->filename_sym) == -1) { @@ -496,12 +547,12 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint32_t * return size; } -static int -write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint32_t filenames_len) +static size_t +write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { uint8_t *cur; - uint32_t f_idx; - uint32_t ret; + uint16_t f_idx; + ptrdiff_t ret; cur = bin + sizeof(uint32_t); /* skip record size */ cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */ @@ -516,8 +567,9 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const /* filename index */ filename_idx = find_filename_index(filenames, filenames_len, file->filename_sym); - mrb_assert(filename_idx != -1); - cur += uint16_to_bin(filename_idx, cur); + mrb_assert(filename_idx >= 0); + mrb_assert(filename_idx <= UINT16_MAX); + cur += uint16_to_bin((uint16_t)filename_idx, cur); /* lines */ cur += uint32_to_bin(file->line_entry_count, cur); @@ -526,15 +578,15 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const case mrb_debug_line_ary: { uint32_t l; for (l = 0; l < file->line_entry_count; ++l) { - cur += uint16_to_bin(file->line_ary[l], cur); + cur += uint16_to_bin(file->lines.ary[l], cur); } } break; case mrb_debug_line_flat_map: { uint32_t line; for (line = 0; line < file->line_entry_count; ++line) { - cur += uint32_to_bin(file->line_flat_map[line].start_pos, cur); - cur += uint16_to_bin(file->line_flat_map[line].line, cur); + cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur); + cur += uint16_to_bin(file->lines.flat_map[line].line, cur); } } break; @@ -543,16 +595,19 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const } ret = cur - bin; + mrb_assert(ret >= 0); + mrb_assert(ret <= UINT32_MAX); uint32_to_bin(ret, bin); - return ret; + mrb_assert((size_t)ret <= SIZE_MAX); + return (size_t)ret; } -static uint32_t -write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint32_t filenames_len) +static size_t +write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { - uint32_t size, len; - uint32_t irep_no; + size_t size, len; + size_t irep_no; size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len); bin += len; @@ -566,14 +621,14 @@ write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* return size; } -static uint32_t -write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, uint32_t *lp) +static size_t +write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, uint16_t *lp) { uint8_t *cur = *cp; mrb_sym *filenames = *fp; uint32_t file_i; uint16_t fn_len; - uint32_t size = 0; + size_t size = 0; mrb_irep_debug_info *debug_info = irep->debug_info; for (file_i = 0; file_i < debug_info->flen; ++file_i) { @@ -603,13 +658,13 @@ write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, static int write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) { - uint32_t section_size = 0; + size_t section_size = 0; const uint8_t *bin = cur; struct rite_section_debug_header *header; mrb_sym *filenames; - uint32_t filenames_len = 0; + uint16_t filenames_len = 0; uint8_t *filenames_len_out; - uint32_t dlen; + size_t dlen; if (mrb == NULL || cur == NULL) { return MRB_DUMP_INVALID_ARGUMENT; @@ -632,6 +687,7 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) section_size += dlen; memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify)); + mrb_assert(section_size <= INT32_MAX); uint32_to_bin(section_size, header->section_size); mrb_free(mrb, filenames); @@ -640,7 +696,7 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) } static int -write_rite_binary_header(mrb_state *mrb, uint32_t binary_size, uint8_t *bin) +write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin) { struct rite_binary_header *header = (struct rite_binary_header *)bin; uint16_t crc; @@ -650,7 +706,8 @@ write_rite_binary_header(mrb_state *mrb, uint32_t binary_size, uint8_t *bin) memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)); memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); - uint32_to_bin(binary_size, header->binary_size); + mrb_assert(binary_size <= UINT32_MAX); + uint32_to_bin((uint32_t)binary_size, header->binary_size); offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t); crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0); @@ -662,7 +719,7 @@ write_rite_binary_header(mrb_state *mrb, uint32_t binary_size, uint8_t *bin) static mrb_bool is_debug_info_defined(mrb_irep *irep) { - uint32_t i; + size_t i; if (!irep->debug_info) return 0; for (i=0; i<irep->rlen; i++) { @@ -672,11 +729,11 @@ is_debug_info_defined(mrb_irep *irep) } static int -dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, uint32_t *bin_size) +dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size) { int result = MRB_DUMP_GENERAL_FAILURE; - uint32_t section_irep_size; - uint32_t section_lineno_size = 0; + size_t section_irep_size; + size_t section_lineno_size = 0; uint8_t *cur = NULL; mrb_bool const debug_info_defined = is_debug_info_defined(irep); @@ -757,7 +814,7 @@ int mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp) { uint8_t *bin = NULL; - uint32_t bin_size = 0; + size_t bin_size = 0; int result; if (fp == NULL) { @@ -793,7 +850,7 @@ int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, const char *initname) { uint8_t *bin = NULL; - uint32_t bin_size = 0, bin_idx = 0; + size_t bin_size = 0, bin_idx = 0; int result; if (fp == NULL || initname == NULL || !is_valid_c_symbol_name(initname)) { @@ -1589,5 +1589,5 @@ gc_test(mrb_state *mrb, mrb_value self) test_incremental_sweep_phase(); return mrb_nil_value(); } -#endif -#endif +#endif /* GC_DEBUG */ +#endif /* GC_TEST */ diff --git a/src/hash.c b/src/hash.c index af3571eaf..86ad4c63d 100644 --- a/src/hash.c +++ b/src/hash.c @@ -18,7 +18,7 @@ mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) khint_t h = (khint_t)mrb_type(key) << 24; mrb_value h2; - h2 = mrb_funcall(mrb, key, "hash", 0, 0); + h2 = mrb_funcall(mrb, key, "hash", 0); h ^= h2.value.i; return h; } @@ -676,14 +676,14 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) str2 = mrb_inspect(mrb, kh_key(h,k)); mrb_str_append(mrb, str, str2); - mrb_str_buf_cat(mrb, str, "=>", 2); + mrb_str_cat_lit(mrb, str, "=>"); str2 = mrb_inspect(mrb, kh_value(h,k)); mrb_str_append(mrb, str, str2); mrb_gc_arena_restore(mrb, ai); } } - mrb_str_buf_cat(mrb, str, "}", 1); + mrb_str_cat_lit(mrb, str, "}"); return str; } @@ -874,6 +874,7 @@ static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) { khash_t(ht) *h1, *h2; + mrb_bool eq; if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { @@ -881,8 +882,6 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) return mrb_false_value(); } else { - mrb_bool eq; - if (eql) { eq = mrb_eql(mrb, hash2, hash1); } @@ -908,7 +907,11 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) key = kh_key(h1,k1); k2 = kh_get(ht, mrb, h2, key); if (k2 != kh_end(h2)) { - if (mrb_eql(mrb, kh_value(h1,k1), kh_value(h2,k2))) { + if (eql) + eq = mrb_eql(mrb, kh_value(h1,k1), kh_value(h2,k2)); + else + eq = mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2)); + if (eq) { continue; /* next key */ } } diff --git a/src/load.c b/src/load.c index de517f89f..5762cf2a2 100644 --- a/src/load.c +++ b/src/load.c @@ -26,6 +26,10 @@ # error This code assumes CHAR_BIT == 8 #endif +#if UINT32_MAX > SIZE_MAX +# error This code cannot be built on your environment. +#endif + static size_t offset_crc_body(void) { @@ -34,10 +38,11 @@ offset_crc_body(void) } static mrb_irep* -read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool alloc) +read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, mrb_bool alloc) { size_t i; const uint8_t *src = bin; + ptrdiff_t diff; uint16_t tt, pool_data_len, snl; size_t plen; int ai = mrb_gc_arena_save(mrb); @@ -55,12 +60,12 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a src += sizeof(uint16_t); /* number of child irep */ - irep->rlen = bin_to_uint16(src); + irep->rlen = (size_t)bin_to_uint16(src); src += sizeof(uint16_t); /* Binary Data Section */ /* ISEQ BLOCK */ - irep->ilen = bin_to_uint32(src); + irep->ilen = (size_t)bin_to_uint32(src); src += sizeof(uint32_t); if (irep->ilen > 0) { if (SIZE_ERROR_MUL(sizeof(mrb_code), irep->ilen)) { @@ -71,13 +76,13 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a return NULL; } for (i = 0; i < irep->ilen; i++) { - irep->iseq[i] = bin_to_uint32(src); /* iseq */ + irep->iseq[i] = (size_t)bin_to_uint32(src); /* iseq */ src += sizeof(uint32_t); } } /* POOL BLOCK */ - plen = bin_to_uint32(src); /* number of pool */ + plen = (size_t)bin_to_uint32(src); /* number of pool */ src += sizeof(uint32_t); if (plen > 0) { if (SIZE_ERROR_MUL(sizeof(mrb_value), plen)) { @@ -125,7 +130,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a } /* SYMS BLOCK */ - irep->slen = bin_to_uint32(src); /* syms length */ + irep->slen = (size_t)bin_to_uint32(src); /* syms length */ src += sizeof(uint32_t); if (irep->slen > 0) { if (SIZE_ERROR_MUL(sizeof(mrb_sym), irep->slen)) { @@ -158,20 +163,24 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool a } irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen); - *len = src - bin; + + diff = src - bin; + mrb_assert(diff >= 0); + mrb_assert((size_t)diff <= SIZE_MAX); + *len = (size_t)diff; return irep; } static mrb_irep* -read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool alloc) +read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, mrb_bool alloc) { mrb_irep *irep = read_irep_record_1(mrb, bin, len, alloc); size_t i; bin += *len; for (i=0; i<irep->rlen; i++) { - uint32_t rlen; + size_t rlen; irep->reps[i] = read_irep_record(mrb, bin, &rlen, alloc); bin += rlen; @@ -183,14 +192,14 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool all static mrb_irep* read_section_irep(mrb_state *mrb, const uint8_t *bin, mrb_bool alloc) { - uint32_t len; + size_t len; bin += sizeof(struct rite_section_irep_header); return read_irep_record(mrb, bin, &len, alloc); } static int -read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_t *len) +read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len) { int ret; size_t i, fname_len, niseq; @@ -216,7 +225,7 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_ bin += fname_len; *len += fname_len; - niseq = bin_to_uint32(bin); + niseq = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); /* niseq */ *len += sizeof(uint32_t); @@ -239,14 +248,14 @@ read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_ } static int -read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_t *lenp) +read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp) { int result = read_lineno_record_1(mrb, bin, irep, lenp); size_t i; if (result != MRB_DUMP_OK) return result; for (i = 0; i < irep->rlen; i++) { - uint32_t len; + size_t len; result = read_lineno_record(mrb, bin, irep->reps[i], &len); if (result != MRB_DUMP_OK) break; @@ -259,7 +268,7 @@ read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, uint32_t static int read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep) { - uint32_t len; + size_t len; len = 0; bin += sizeof(struct rite_section_lineno_header); @@ -269,9 +278,10 @@ read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep) } static int -read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t *len, const mrb_sym *filenames, size_t filenames_len) +read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len) { const uint8_t *bin = start; + ptrdiff_t diff; size_t record_size, i; uint16_t f_idx; @@ -280,7 +290,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); irep->debug_info->pc_count = irep->ilen; - record_size = bin_to_uint32(bin); + record_size = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); irep->debug_info->flen = bin_to_uint16(bin); @@ -295,7 +305,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); irep->debug_info->files[f_idx] = file; - file->start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); + file->start_pos = bin_to_uint32(bin); + bin += sizeof(uint32_t); /* filename */ filename_idx = bin_to_uint16(bin); @@ -305,26 +316,31 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t len = 0; file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len); - file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t); - file->line_type = (mrb_debug_line_type)bin_to_uint8(bin); bin += sizeof(uint8_t); + file->line_entry_count = bin_to_uint32(bin); + bin += sizeof(uint32_t); + file->line_type = (mrb_debug_line_type)bin_to_uint8(bin); + bin += sizeof(uint8_t); switch(file->line_type) { case mrb_debug_line_ary: { - size_t l; + uint32_t l; - file->line_ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * file->line_entry_count); + file->lines.ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * (size_t)(file->line_entry_count)); for(l = 0; l < file->line_entry_count; ++l) { - file->line_ary[l] = bin_to_uint16(bin); bin += sizeof(uint16_t); + file->lines.ary[l] = bin_to_uint16(bin); + bin += sizeof(uint16_t); } } break; case mrb_debug_line_flat_map: { - size_t l; + uint32_t l; - file->line_flat_map = (mrb_irep_debug_info_line*)mrb_malloc( - mrb, sizeof(mrb_irep_debug_info_line) * file->line_entry_count); + file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc( + mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count)); for(l = 0; l < file->line_entry_count; ++l) { - file->line_flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); - file->line_flat_map[l].line = bin_to_uint16(bin); bin += sizeof(uint16_t); + file->lines.flat_map[l].start_pos = bin_to_uint32(bin); + bin += sizeof(uint32_t); + file->lines.flat_map[l].line = bin_to_uint16(bin); + bin += sizeof(uint16_t); } } break; @@ -332,12 +348,16 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t } } - if((long)record_size != (bin - start)) { + diff = bin - start; + mrb_assert(diff >= 0); + mrb_assert((size_t)diff <= SIZE_MAX); + + if(record_size != (size_t)diff) { return MRB_DUMP_GENERAL_FAILURE; } for (i = 0; i < irep->rlen; i++) { - uint32_t len; + size_t len; int ret; ret =read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len); @@ -345,7 +365,10 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t bin += len; } - *len = bin - start; + diff = bin - start; + mrb_assert(diff >= 0); + mrb_assert((size_t)diff <= SIZE_MAX); + *record_len = (size_t)diff; return MRB_DUMP_OK; } @@ -354,11 +377,12 @@ static int read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_bool alloc) { const uint8_t *bin; + ptrdiff_t diff; struct rite_section_debug_header *header; uint16_t i; - uint32_t len = 0; + size_t len = 0; int result; - size_t filenames_len; + uint16_t filenames_len; mrb_sym *filenames; bin = start; @@ -367,15 +391,15 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_boo filenames_len = bin_to_uint16(bin); bin += sizeof(uint16_t); - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * filenames_len); + filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len); for(i = 0; i < filenames_len; ++i) { uint16_t f_len = bin_to_uint16(bin); bin += sizeof(uint16_t); if (alloc) { - filenames[i] = mrb_intern(mrb, (const char *)bin, f_len); + filenames[i] = mrb_intern(mrb, (const char *)bin, (size_t)f_len); } else { - filenames[i] = mrb_intern_static(mrb, (const char *)bin, f_len); + filenames[i] = mrb_intern_static(mrb, (const char *)bin, (size_t)f_len); } bin += f_len; } @@ -384,7 +408,10 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_boo if (result != MRB_DUMP_OK) goto debug_exit; bin += len; - if ((bin - start) != bin_to_uint32(header->section_size)) { + diff = bin - start; + mrb_assert(diff >= 0); + mrb_assert(diff <= UINT32_MAX); + if ((uint32_t)diff != bin_to_uint32(header->section_size)) { result = MRB_DUMP_GENERAL_FAILURE; } @@ -408,7 +435,7 @@ read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc) *crc = bin_to_uint16(header->binary_crc); if (bin_size) { - *bin_size = bin_to_uint32(header->binary_size); + *bin_size = (size_t)bin_to_uint32(header->binary_size); } return MRB_DUMP_OK; @@ -504,14 +531,14 @@ read_lineno_record_file(mrb_state *mrb, FILE *fp, mrb_irep *irep) const size_t record_header_size = sizeof(header); int result; size_t i, buf_size; - uint32_t len; + size_t len; void *ptr; uint8_t *buf; if (fread(header, record_header_size, 1, fp) == 0) { return MRB_DUMP_READ_FAULT; } - buf_size = bin_to_uint32(&header[0]); + buf_size = (size_t)bin_to_uint32(&header[0]); if (SIZE_ERROR(buf_size)) { return MRB_DUMP_GENERAL_FAILURE; } @@ -553,7 +580,7 @@ read_irep_record_file(mrb_state *mrb, FILE *fp) uint8_t header[1 + 4]; const size_t record_header_size = sizeof(header); size_t buf_size, i; - uint32_t len; + size_t len; mrb_irep *irep = NULL; void *ptr; uint8_t *buf; @@ -561,7 +588,7 @@ read_irep_record_file(mrb_state *mrb, FILE *fp) if (fread(header, record_header_size, 1, fp) == 0) { return NULL; } - buf_size = bin_to_uint32(&header[0]); + buf_size = (size_t)bin_to_uint32(&header[0]); if (SIZE_ERROR(buf_size)) { return NULL; } @@ -600,7 +627,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) int result; uint8_t *buf; uint16_t crc, crcwk = 0; - uint32_t section_size = 0; + size_t section_size = 0; size_t nbytes; struct rite_section_header section_header; long fpos; @@ -657,7 +684,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) if (fread(§ion_header, sizeof(struct rite_section_header), 1, fp) == 0) { return NULL; } - section_size = bin_to_uint32(section_header.section_size); + section_size = (size_t)bin_to_uint32(section_header.section_size); if (memcmp(section_header.section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header.section_identify)) == 0) { fseek(fp, fpos, SEEK_SET); diff --git a/src/mrb_throw.h b/src/mrb_throw.h index 859729be6..3c7407a8d 100644 --- a/src/mrb_throw.h +++ b/src/mrb_throw.h @@ -38,4 +38,4 @@ struct mrb_jmpbuf { #endif }; -#endif +#endif /* MRB_THROW_H */ diff --git a/src/numeric.c b/src/numeric.c index 5f23b2461..5d0269e00 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -304,8 +304,8 @@ flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float * mrb_float mod; if (y == 0.0) { - div = str_to_mrb_float("inf"); - mod = str_to_mrb_float("nan"); + div = INFINITY; + mod = NAN; } else { mod = fmod(x, y); @@ -775,7 +775,7 @@ fix_mod(mrb_state *mrb, mrb_value x) mrb_int mod; if (mrb_fixnum(y) == 0) { - return mrb_float_value(mrb, str_to_mrb_float("nan")); + return mrb_float_value(mrb, NAN); } fixdivmod(mrb, a, mrb_fixnum(y), 0, &mod); return mrb_fixnum_value(mod); @@ -805,8 +805,8 @@ fix_divmod(mrb_state *mrb, mrb_value x) mrb_int div, mod; if (mrb_fixnum(y) == 0) { - return mrb_assoc_new(mrb, mrb_float_value(mrb, str_to_mrb_float("inf")), - mrb_float_value(mrb, str_to_mrb_float("nan"))); + return mrb_assoc_new(mrb, mrb_float_value(mrb, INFINITY), + mrb_float_value(mrb, NAN)); } fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); diff --git a/src/object.c b/src/object.c index 2f14c5698..5090e38cf 100644 --- a/src/object.c +++ b/src/object.c @@ -440,11 +440,11 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) mrb_value str = mrb_str_buf_new(mrb, 20); const char *cname = mrb_obj_classname(mrb, obj); - mrb_str_buf_cat(mrb, str, "#<", 2); + mrb_str_cat_lit(mrb, str, "#<"); mrb_str_cat_cstr(mrb, str, cname); mrb_str_cat_lit(mrb, str, ":"); mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj))); - mrb_str_buf_cat(mrb, str, ">", 1); + mrb_str_cat_lit(mrb, str, ">"); return str; } @@ -588,7 +588,7 @@ mrb_Float(mrb_state *mrb, mrb_value val) mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { - return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0, 0)); + return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0)); } mrb_bool diff --git a/src/parse.y b/src/parse.y index b82b3e271..c3460555d 100644 --- a/src/parse.y +++ b/src/parse.y @@ -3526,8 +3526,8 @@ static int scan_hex(const int *start, int len, int *retlen) { static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; - register const int *s = start; - register int retval = 0; + const int *s = start; + int retval = 0; char *tmp; /* mrb_assert(len <= 2) */ @@ -3932,7 +3932,7 @@ arg_ambiguous(parser_state *p) static int parser_yylex(parser_state *p) { - register int c; + int c; int space_seen = 0; int cmd_state; enum mrb_lex_state_enum last_state; diff --git a/src/pool.c b/src/pool.c index f09df92c5..4d8c42dd1 100644 --- a/src/pool.c +++ b/src/pool.c @@ -5,6 +5,7 @@ */ #include <stddef.h> +#include <stdint.h> #include <string.h> #include "mruby.h" @@ -36,12 +37,12 @@ struct mrb_pool { #undef TEST_POOL #ifdef TEST_POOL -#define mrb_malloc(m,s) malloc(s) +#define mrb_malloc_simple(m,s) malloc(s) #define mrb_free(m,p) free(p) #endif #ifdef POOL_ALIGNMENT -# define ALIGN_PADDING(x) ((-x) & (POOL_ALIGNMENT - 1)) +# define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1)) #else # define ALIGN_PADDING(x) (0) #endif @@ -49,7 +50,7 @@ struct mrb_pool { mrb_pool* mrb_pool_open(mrb_state *mrb) { - mrb_pool *pool = (mrb_pool *)mrb_malloc(mrb, sizeof(mrb_pool)); + mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool)); if (pool) { pool->mrb = mrb; @@ -81,7 +82,7 @@ page_alloc(mrb_pool *pool, size_t len) if (len < POOL_PAGE_SIZE) len = POOL_PAGE_SIZE; - page = (struct mrb_pool_page *)mrb_malloc(pool->mrb, sizeof(struct mrb_pool_page)+len); + page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len); if (page) { page->offset = 0; page->len = len; @@ -9,4 +9,4 @@ #define REGEXP_CLASS "Regexp" -#endif +#endif /* RE_H */ diff --git a/src/string.c b/src/string.c index 85a3cc2a7..dff8de90f 100644 --- a/src/string.c +++ b/src/string.c @@ -41,7 +41,7 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; typedef struct mrb_shared_string { - mrb_bool nofree; + mrb_bool nofree : 1; int refcnt; char *ptr; mrb_int len; @@ -54,6 +54,21 @@ typedef struct mrb_shared_string { static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); +mrb_int +mrb_str_strlen(mrb_state *mrb, struct RString *s) +{ + mrb_int i, max = STR_LEN(s); + char *p = STR_PTR(s); + + if (!p) return 0; + for (i=0; i<max; i++) { + if (p[i] == '\0') { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); + } + } + return max; +} + #define RESIZE_CAPA(s,capacity) do {\ if (STR_EMBED_P(s)) {\ if (RSTRING_EMBED_LEN_MAX < (capacity)) {\ @@ -2066,12 +2081,14 @@ char * mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) { struct RString *ps = mrb_str_ptr(*ptr); - char *s = STR_PTR(ps); + mrb_int len = mrb_str_strlen(mrb, ps); + char *p = STR_PTR(ps); - if (!s || STR_LEN(ps) != strlen(s)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); + if (!p || p[len] != '\0') { + mrb_str_modify(mrb, ps); + return STR_PTR(ps); } - return s; + return p; } mrb_value @@ -2518,7 +2535,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) continue; } } - mrb_str_buf_cat(mrb, result, "\"", 1); + mrb_str_cat_lit(mrb, result, "\""); return result; } diff --git a/src/symbol.c b/src/symbol.c index 95e8ed290..2a7dfa795 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -12,7 +12,7 @@ /* ------------------------------------------------------ */ typedef struct symbol_name { - mrb_bool lit; + mrb_bool lit : 1; uint16_t len; const char *name; } symbol_name; @@ -35,7 +35,7 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1) KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ static mrb_sym -sym_intern(mrb_state *mrb, const char *name, size_t len, int lit) +sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -72,13 +72,13 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, int lit) mrb_sym mrb_intern(mrb_state *mrb, const char *name, size_t len) { - return sym_intern(mrb, name, len, 0); + return sym_intern(mrb, name, len, FALSE); } mrb_sym mrb_intern_static(mrb_state *mrb, const char *name, size_t len) { - return sym_intern(mrb, name, len, 1); + return sym_intern(mrb, name, len, TRUE); } mrb_sym diff --git a/src/variable.c b/src/variable.c index c313a8f14..bfffb727f 100644 --- a/src/variable.c +++ b/src/variable.c @@ -596,7 +596,7 @@ mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); mrb_value str = mrb_str_buf_new(mrb, 30); - mrb_str_buf_cat(mrb, str, "-<", 2); + mrb_str_cat_lit(mrb, str, "-<"); mrb_str_cat_cstr(mrb, str, cn); mrb_str_cat_lit(mrb, str, ":"); mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj)); diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index daf0bec3a..60d6672f0 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -43,6 +43,10 @@ module MRuby MRuby::Gem.current = self end + def run_test_in_other_mrb_state? + not test_preload.nil? or not test_objs.empty? + end + def cxx_abi_enabled? @cxx_abi_enabled end diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake index 33f1fdb48..4c27686f2 100644 --- a/tasks/mrbgems_test.rake +++ b/tasks/mrbgems_test.rake @@ -1,5 +1,12 @@ MRuby.each_target do + no_mrb_open_test_gem = [] + gems.each do |g| + unless g.run_test_in_other_mrb_state? + no_mrb_open_test_gem << g + next + end + test_rbobj = g.test_rbireps.ext(exts.object) file test_rbobj => g.test_rbireps @@ -10,6 +17,13 @@ MRuby.each_target do File.expand_path(g.test_preload, dir) }.find {|file| File.exist?(file) } + f.puts %Q[/*] + f.puts %Q[ * This file contains a test code for #{g.name} gem.] + f.puts %Q[ *] + f.puts %Q[ * IMPORTANT:] + f.puts %Q[ * This file was generated!] + f.puts %Q[ * All manual changes will get lost.] + f.puts %Q[ */] if test_preload.nil? f.puts %Q[extern const uint8_t mrbtest_assert_irep[];] else @@ -79,8 +93,7 @@ MRuby.each_target do f.puts %Q[ val2 = mrb_ary_shift(mrb2, ary2);] f.puts %Q[ ] f.puts %Q[ while (mrb_test(val2)) {] - f.puts %Q[ char *str = mrb_string_value_cstr(mrb2, &val2);] - f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new_cstr(mrb, str));] + f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new(mrb, RSTRING_PTR(val2), RSTRING_LEN(val2)));] f.puts %Q[ val2 = mrb_ary_shift(mrb2, ary2);] f.puts %Q[ }] f.puts %Q[ }] @@ -93,4 +106,37 @@ MRuby.each_target do end end + + no_mrb_open_test = "#{build_dir}/test/no_mrb_open_test" + no_mrb_open_test_rbfiles = no_mrb_open_test_gem.reduce([]) { |res, v| + res += v.test_rbfiles + } + file "#{no_mrb_open_test}.o" => "#{no_mrb_open_test}.c" + file "#{no_mrb_open_test}.c" => no_mrb_open_test_rbfiles do |t| + open(t.name, 'w') do |f| + f.puts %Q[/*] + f.puts %Q[ * This file contains a test code for following gems:] + no_mrb_open_test_gem.each { |g| f.puts %Q[ * #{g.name}] } + f.puts %Q[ *] + f.puts %Q[ * IMPORTANT:] + f.puts %Q[ * This file was generated!] + f.puts %Q[ * All manual changes will get lost.] + f.puts %Q[ */] + + f.puts %Q[] + + f.puts %Q[\#include "mruby.h"] + f.puts %Q[\#include "mruby/irep.h"] + + f.puts %Q[] + + mrbc.run f, no_mrb_open_test_rbfiles, "no_mrb_open_gem_test_irep" + + f.puts %Q[] + + f.puts %Q[void no_mrb_open_mrbgem_test(mrb_state *mrb) {] + f.puts %Q[ mrb_load_irep(mrb, no_mrb_open_gem_test_irep);] + f.puts %Q[}] + end + end end diff --git a/test/assert.rb b/test/assert.rb index d2d865649..1e9a781d6 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -174,6 +174,24 @@ def assert_raise(*exp) ret end +def assert_nothing_raised(*exp) + ret = true + if $mrbtest_assert + $mrbtest_assert_idx += 1 + msg = exp.last.class == String ? exp.pop : "" + begin + yield + rescue Exception => e + msg = "#{msg} exception raised." + diff = " Class: <#{e.class}>\n" + + " Message: #{e.message}" + $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff]) + ret = false + end + end + ret +end + ## # Fails unless +obj+ is a kind of +cls+. def assert_kind_of(cls, obj, msg = nil) diff --git a/test/mrbtest.rake b/test/mrbtest.rake index 35495889e..1c52eafbd 100644 --- a/test/mrbtest.rake +++ b/test/mrbtest.rake @@ -12,9 +12,11 @@ MRuby.each_target do ass_lib = ass_c.ext(exts.object) mrbtest_lib = libfile("#{current_build_dir}/mrbtest") - file mrbtest_lib => [mlib, ass_lib, gems.map(&:test_objs), gems.map { |g| g.test_rbireps.ext(exts.object) }].flatten do |t| + gem_test_files = gems.select { |g| g.run_test_in_other_mrb_state? }.map { |g| g.test_rbireps.ext(exts.object) } + file mrbtest_lib => [mlib, ass_lib, gems.map(&:test_objs), gem_test_files].flatten do |t| archiver.run t.name, t.prerequisites end + file mrbtest_lib => "#{build_dir}/test/no_mrb_open_test.o" unless build_mrbtest_lib_only? driver_obj = objfile("#{current_build_dir}/driver") @@ -41,15 +43,28 @@ MRuby.each_target do _pp "GEN", "*.rb", "#{clib.relative_path}" FileUtils.mkdir_p File.dirname(clib) open(clib, 'w') do |f| + f.puts %Q[/*] + f.puts %Q[ * This file contains a list of all] + f.puts %Q[ * test functions.] + f.puts %Q[ *] + f.puts %Q[ * IMPORTANT:] + f.puts %Q[ * This file was generated!] + f.puts %Q[ * All manual changes will get lost.] + f.puts %Q[ */] + f.puts %Q[] f.puts IO.read(init) mrbc.run f, mrbs, 'mrbtest_irep' gems.each do |g| + next unless g.run_test_in_other_mrb_state? f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);] end + f.puts %Q[void no_mrb_open_mrbgem_test(mrb_state *mrb);] f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {] gems.each do |g| + next unless g.run_test_in_other_mrb_state? f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);] end + f.puts %Q[ no_mrb_open_mrbgem_test(mrb);] f.puts %Q[}] end end diff --git a/test/t/hash.rb b/test/t/hash.rb index 92bc223b6..e7d5e8f74 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -12,6 +12,7 @@ end assert('Hash#==', '15.2.13.4.1') do assert_true({ 'abc' => 'abc' } == { 'abc' => 'abc' }) assert_false({ 'abc' => 'abc' } == { 'cba' => 'cba' }) + assert_true({ :equal => 1 } == { :equal => 1.0 }) end assert('Hash#[]', '15.2.13.4.2') do |
