diff --git a/array.c b/array.c
index 0b5601d..a6a1e89 100644
--- a/array.c
+++ b/array.c
@@ -20,6 +20,7 @@ VALUE rb_cArray;
 static ID id_cmp;
 
 #define ARY_DEFAULT_SIZE 16
+#define	ARY_MAX_SIZE (LONG_MAX / sizeof(VALUE))
 
 void
 rb_mem_clear(mem, size)
@@ -120,7 +121,7 @@ ary_new(klass, len)
     if (len < 0) {
 	rb_raise(rb_eArgError, "negative array size (or size too big)");
     }
-    if (len > 0 && len * sizeof(VALUE) <= len) {
+    if (len > ARY_MAX_SIZE) {
 	rb_raise(rb_eArgError, "array size too big");
     }
     if (len == 0) len++;
@@ -293,7 +294,7 @@ rb_ary_initialize(argc, argv, ary)
     if (len < 0) {
 	rb_raise(rb_eArgError, "negative array size");
     }
-    if (len > 0 && len * (long)sizeof(VALUE) <= len) {
+    if (len > ARY_MAX_SIZE) {
 	rb_raise(rb_eArgError, "array size too big");
     }
     if (len > RARRAY(ary)->aux.capa) {
@@ -359,6 +360,10 @@ rb_ary_store(ary, idx, val)
 	}
     }
 
+    if (idx >= ARY_MAX_SIZE) {
+        rb_raise(rb_eIndexError, "index %ld too big", idx);
+    }
+
     rb_ary_modify(ary);
     if (idx >= RARRAY(ary)->aux.capa) {
 	long new_capa = RARRAY(ary)->aux.capa / 2;
@@ -366,6 +371,9 @@ rb_ary_store(ary, idx, val)
 	if (new_capa < ARY_DEFAULT_SIZE) {
 	    new_capa = ARY_DEFAULT_SIZE;
 	}
+	if (new_capa >= ARY_MAX_SIZE - idx) {
+	    new_capa = (ARY_MAX_SIZE - idx) / 2;
+	}
 	new_capa += idx;
 	if (new_capa * (long)sizeof(VALUE) <= new_capa) {
 	    rb_raise(rb_eArgError, "index too big");
@@ -975,6 +983,9 @@ rb_ary_splice(ary, beg, len, rpl)
     rb_ary_modify(ary);
 
     if (beg >= RARRAY(ary)->len) {
+	if (beg > ARY_MAX_SIZE - rlen) {
+	    rb_raise(rb_eIndexError, "index %ld too big", beg);
+	}
 	len = beg + rlen;
 	if (len >= RARRAY(ary)->aux.capa) {
 	    REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
@@ -2378,7 +2389,7 @@ rb_ary_times(ary, times)
     if (len < 0) {
 	rb_raise(rb_eArgError, "negative argument");
     }
-    if (LONG_MAX/len < RARRAY(ary)->len) {
+    if (ARY_MAX_SIZE/len < RARRAY(ary)->len) {
 	rb_raise(rb_eArgError, "argument too big");
     }
     len *= RARRAY(ary)->len;
diff --git a/bignum.c b/bignum.c
index 1fcc924..8674fe2 100644
--- a/bignum.c
+++ b/bignum.c
@@ -36,7 +36,21 @@ VALUE rb_cBignum;
 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
 #define BDIGMAX ((BDIGIT)-1)
 
-#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0))
+#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || \
+		     (BDIGITS(x)[0] == 0 && \
+		      (RBIGNUM(x)->len == 1 || bigzero_p(x))))
+
+static int bigzero_p(VALUE);
+static int
+bigzero_p(x)
+    VALUE x;
+{
+    long i;
+    for (i = 0; i < RBIGNUM(x)->len; ++i) {
+	if (BDIGITS(x)[i]) return 0;
+    }
+    return 1;
+}
 
 static VALUE
 bignew_1(klass, len, sign)
@@ -446,7 +460,7 @@ rb_cstr_to_inum(str, base, badcheck)
     }
     if (*str == '0') {		/* squeeze preceeding 0s */
 	while (*++str == '0');
-	if (!*str) --str;
+	if (!(c = *str) || ISSPACE(c)) --str;
     }
     c = *str;
     c = conv_digit(c);
@@ -652,6 +666,9 @@ rb_big2str0(x, base, trim)
     if (BIGZEROP(x)) {
 	return rb_str_new2("0");
     }
+    if (i >= LONG_MAX/SIZEOF_BDIGITS/CHAR_BIT) {
+	rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
+    }
     j = SIZEOF_BDIGITS*CHAR_BIT*i;
     switch (base) {
       case 2: break;
@@ -706,7 +723,7 @@ rb_big2str0(x, base, trim)
 	while (k--) {
 	    s[--j] = ruby_digitmap[num % base];
 	    num /= base;
-	    if (!trim && j < 1) break;
+	    if (!trim && j <= 1) break;
 	    if (trim && i == 0 && num == 0) break;
 	}
     }
diff --git a/eval.c b/eval.c
index 1e7cf6d..4164b9b 100644
--- a/eval.c
+++ b/eval.c
@@ -8332,16 +8332,25 @@ proc_clone(self)
  * MISSING: documentation
  */
 
+#define PROC_TSHIFT (FL_USHIFT+1)
+#define PROC_TMASK  (FL_USER1|FL_USER2|FL_USER3)
+#define PROC_TMAX   (PROC_TMASK >> PROC_TSHIFT)
+
+static int proc_get_safe_level(VALUE);
+
 static VALUE
 proc_dup(self)
     VALUE self;
 {
     struct BLOCK *orig, *data;
     VALUE bind;
+    int safe = proc_get_safe_level(self);
 
     Data_Get_Struct(self, struct BLOCK, orig);
     bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
     blk_dup(data, orig);
+    if (safe > PROC_TMAX) safe = PROC_TMAX;
+    FL_SET(bind, (safe << PROC_TSHIFT) & PROC_TMASK);
 
     return bind;
 }
@@ -8403,10 +8412,6 @@ rb_f_binding(self)
     return bind;
 }
 
-#define PROC_TSHIFT (FL_USHIFT+1)
-#define PROC_TMASK  (FL_USER1|FL_USER2|FL_USER3)
-#define PROC_TMAX   (PROC_TMASK >> PROC_TSHIFT)
-
 #define SAFE_LEVEL_MAX PROC_TMASK
 
 static void
diff --git a/intern.h b/intern.h
index 822066c..99c4ade 100644
--- a/intern.h
+++ b/intern.h
@@ -400,6 +400,7 @@ const char *ruby_signal_name _((int));
 void ruby_default_signal _((int));
 /* sprintf.c */
 VALUE rb_f_sprintf _((int, VALUE*));
+VALUE rb_str_format _((int, VALUE*, VALUE));
 /* string.c */
 VALUE rb_str_new _((const char*, long));
 VALUE rb_str_new2 _((const char*));
diff --git a/io.c b/io.c
index 4ffad84..c4cca9d 100644
--- a/io.c
+++ b/io.c
@@ -4851,8 +4851,9 @@ rb_f_select(argc, argv, obj)
 #if !defined(MSDOS) && !defined(__human68k__)
 static int
 io_cntl(fd, cmd, narg, io_p)
-    int fd, cmd, io_p;
+    int fd, io_p;
     long narg;
+    unsigned long cmd;
 {
     int retval;
 
@@ -4882,7 +4883,7 @@ rb_io_ctl(io, req, arg, io_p)
     int io_p;
 {
 #if !defined(MSDOS) && !defined(__human68k__)
-    int cmd = NUM2ULONG(req);
+    unsigned long cmd = NUM2ULONG(req);
     OpenFile *fptr;
     long len = 0;
     long narg = 0;
diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb
index 410cc6f..c8278b7 100644
--- a/lib/webrick/httpservlet/filehandler.rb
+++ b/lib/webrick/httpservlet/filehandler.rb
@@ -163,6 +163,7 @@ module WEBrick
             end
           end
         end
+        prevent_directory_traversal(req, res)
         super(req, res)
       end
 
@@ -198,6 +199,22 @@ module WEBrick
 
       private
 
+      def prevent_directory_traversal(req, res)
+        # Preventing directory traversal on DOSISH platforms;
+        # Backslashes (0x5c) in path_info are not interpreted as special
+        # character in URI notation. So the value of path_info should be
+        # normalize before accessing to the filesystem.
+        if File::ALT_SEPARATOR
+          # File.expand_path removes the trailing path separator.
+          # Adding a character is a workaround to save it.
+          #  File.expand_path("/aaa/")        #=> "/aaa"
+          #  File.expand_path("/aaa/" + "x")  #=> "/aaa/x"
+          expanded = File.expand_path(req.path_info + "x")
+          expanded[-1, 1] = ""  # remove trailing "x"
+          req.path_info = expanded
+        end
+      end
+
       def exec_handler(req, res)
         raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
         if set_filename(req, res)
@@ -256,7 +273,7 @@ module WEBrick
 
       def check_filename(req, res, name)
         @options[:NondisclosureName].each{|pattern|
-          if File.fnmatch("/#{pattern}", name)
+          if File.fnmatch("/#{pattern}", name, File::FNM_CASEFOLD)
             @logger.warn("the request refers nondisclosure name `#{name}'.")
             raise HTTPStatus::NotFound, "`#{req.path}' not found."
           end
@@ -310,7 +327,7 @@ module WEBrick
 
       def nondisclosure_name?(name)
         @options[:NondisclosureName].each{|pattern|
-          if File.fnmatch(pattern, name)
+          if File.fnmatch(pattern, name, File::FNM_CASEFOLD)
             return true
           end
         }
diff --git a/sprintf.c b/sprintf.c
index 9700c80..662da6c 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -247,7 +247,15 @@ rb_f_sprintf(argc, argv)
     int argc;
     VALUE *argv;
 {
+    return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
+}
+
+VALUE
+rb_str_format(argc, argv, fmt)
+    int argc;
+    VALUE *argv;
     VALUE fmt;
+{
     const char *p, *end;
     char *buf;
     int blen, bsiz;
@@ -276,7 +284,8 @@ rb_f_sprintf(argc, argv)
 	rb_raise(rb_eArgError, "flag after precision"); \
     }
 
-    fmt = GETNTHARG(0);
+    ++argc;
+    --argv;
     if (OBJ_TAINTED(fmt)) tainted = 1;
     StringValue(fmt);
     fmt = rb_str_new4(fmt);
diff --git a/string.c b/string.c
index 52ec322..623f76f 100644
--- a/string.c
+++ b/string.c
@@ -452,22 +452,16 @@ rb_str_times(str, times)
  */
 
 static VALUE
-rb_str_format(str, arg)
+rb_str_format_m(str, arg)
     VALUE str, arg;
 {
-    VALUE *argv;
+    VALUE tmp = rb_check_array_type(arg);
 
-    if (TYPE(arg) == T_ARRAY) {
-	argv = ALLOCA_N(VALUE, RARRAY(arg)->len + 1);
-	argv[0] = str;
-	MEMCPY(argv+1, RARRAY(arg)->ptr, VALUE, RARRAY(arg)->len);
-	return rb_f_sprintf(RARRAY(arg)->len+1, argv);
+    if (!NIL_P(tmp)) {
+	return rb_str_format(RARRAY_LEN(tmp), RARRAY_PTR(tmp), str);
     }
 
-    argv = ALLOCA_N(VALUE, 2);
-    argv[0] = str;
-    argv[1] = arg;
-    return rb_f_sprintf(2, argv);
+    return rb_str_format(1, &arg, str);
 }
 
 static int
@@ -694,18 +688,14 @@ rb_str_resize(str, len)
     return str;
 }
 
-VALUE
-rb_str_buf_cat(str, ptr, len)
+static VALUE
+str_buf_cat(str, ptr, len)
     VALUE str;
     const char *ptr;
     long len;
 {
     long capa, total;
 
-    if (len == 0) return str;
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative string size (or size too big)");
-    }
     rb_str_modify(str);
     if (FL_TEST(str, STR_ASSOC)) {
 	FL_UNSET(str, STR_ASSOC);
@@ -714,9 +704,16 @@ rb_str_buf_cat(str, ptr, len)
     else {
 	capa = RSTRING(str)->aux.capa;
     }
+    if (RSTRING(str)->len >= LONG_MAX - len) {
+	rb_raise(rb_eArgError, "string sizes too big");
+    }
     total = RSTRING(str)->len+len;
     if (capa <= total) {
 	while (total > capa) {
+	    if (capa + 1 >= LONG_MAX / 2) {
+		capa = total;
+		break;
+	    }
 	    capa = (capa + 1) * 2;
 	}
 	RESIZE_CAPA(str, capa);
@@ -729,6 +726,19 @@ rb_str_buf_cat(str, ptr, len)
 }
 
 VALUE
+rb_str_buf_cat(str, ptr, len)
+    VALUE str;
+    const char *ptr;
+    long len;
+{
+    if (len == 0) return str;
+    if (len < 0) {
+	rb_raise(rb_eArgError, "negative string size (or size too big)");
+    }
+    return str_buf_cat(str, ptr, len);
+}
+
+VALUE
 rb_str_buf_cat2(str, ptr)
     VALUE str;
     const char *ptr;
@@ -747,7 +757,7 @@ rb_str_cat(str, ptr, len)
     }
     if (FL_TEST(str, STR_ASSOC)) {
 	rb_str_modify(str);
-	REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
+	REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len+1);
 	memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
 	RSTRING(str)->len += len;
 	RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
@@ -769,29 +779,8 @@ VALUE
 rb_str_buf_append(str, str2)
     VALUE str, str2;
 {
-    long capa, len;
-
-    rb_str_modify(str);
-    if (FL_TEST(str, STR_ASSOC)) {
-	FL_UNSET(str, STR_ASSOC);
-	capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
-    }
-    else {
-	capa = RSTRING(str)->aux.capa;
-    }
-    len = RSTRING(str)->len+RSTRING(str2)->len;
-    if (capa <= len) {
-	while (len > capa) {
-	    capa = (capa + 1) * 2;
-	}
-	RESIZE_CAPA(str, capa);
-    }
-    memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
-	   RSTRING(str2)->ptr, RSTRING(str2)->len);
-    RSTRING(str)->len += RSTRING(str2)->len;
-    RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
+    str_buf_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
     OBJ_INFECT(str, str2);
-
     return str;
 }
 
@@ -4657,7 +4646,7 @@ Init_String()
     rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
     rb_define_method(rb_cString, "+", rb_str_plus, 1);
     rb_define_method(rb_cString, "*", rb_str_times, 1);
-    rb_define_method(rb_cString, "%", rb_str_format, 1);
+    rb_define_method(rb_cString, "%", rb_str_format_m, 1);
     rb_define_method(rb_cString, "[]", rb_str_aref_m, -1);
     rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1);
     rb_define_method(rb_cString, "insert", rb_str_insert, 2);

