[前][次][番号順一覧][スレッド一覧]

ruby-changes:21627

From: nobu <ko1@a...>
Date: Tue, 8 Nov 2011 23:34:55 +0900 (JST)
Subject: [ruby-changes:21627] nobu:r33676 (trunk): * ext/dbm/dbm.c (fdbm_fetch, fdbm_key, fdbm_delete, fdbm_store)

nobu	2011-11-08 23:34:39 +0900 (Tue, 08 Nov 2011)

  New Revision: 33676

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33676

  Log:
    * ext/dbm/dbm.c (fdbm_fetch, fdbm_key, fdbm_delete, fdbm_store)
      (fdbm_has_key, fdbm_has_value): get rid of overflow.
    * ext/gdbm/gdbm.c (rb_gdbm_fetch2, rb_gdbm_nextkey)
      (rb_gdbm_delete, fgdbm_store, fgdbm_has_key): ditto.
    * ext/dbm/dbm.c (fdbm_delete_if): hide intermediate objects.
    * ext/gdbm/gdbm.c (fgdbm_delete_if): ditto.
    * ext/dbm/extconf.rb: check size of datum.dsize to get rid of
      overflow.

  Modified files:
    trunk/ChangeLog
    trunk/ext/dbm/dbm.c
    trunk/ext/dbm/extconf.rb
    trunk/ext/gdbm/gdbm.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 33675)
+++ ChangeLog	(revision 33676)
@@ -1,3 +1,18 @@
+Tue Nov  8 23:34:37 2011  Nobuyoshi Nakada  <nobu@r...>
+
+	* ext/dbm/dbm.c (fdbm_fetch, fdbm_key, fdbm_delete, fdbm_store)
+	  (fdbm_has_key, fdbm_has_value): get rid of overflow.
+
+	* ext/gdbm/gdbm.c (rb_gdbm_fetch2, rb_gdbm_nextkey)
+	  (rb_gdbm_delete, fgdbm_store, fgdbm_has_key): ditto.
+
+	* ext/dbm/dbm.c (fdbm_delete_if): hide intermediate objects.
+
+	* ext/gdbm/gdbm.c (fgdbm_delete_if): ditto.
+
+	* ext/dbm/extconf.rb: check size of datum.dsize to get rid of
+	  overflow.
+
 Tue Nov  8 23:30:21 2011  NARUSE, Yui  <naruse@r...>
 
 	* addr2line.c (PATH_MAX): define if not defined. [ruby-core:40840]
Index: ext/dbm/dbm.c
===================================================================
--- ext/dbm/dbm.c	(revision 33675)
+++ ext/dbm/dbm.c	(revision 33676)
@@ -21,6 +21,16 @@
 #include <fcntl.h>
 #include <errno.h>
 
+#if SIZEOF_DSIZE > SIZEOF_INT
+# define DSIZE_TYPE long
+# define RSTRING_DSIZE(s) RSTRING_LEN(s)
+# define TOO_LONG(n) 0
+#else
+# define DSIZE_TYPE int
+# define RSTRING_DSIZE(s) RSTRING_LENINT(s)
+# define TOO_LONG(n) ((long)(+(DSIZE_TYPE)(n)) != (n))
+#endif
+
 static VALUE rb_cDBM, rb_eDBMError;
 
 #define RUBY_DBM_RW_BIT 0x20000000
@@ -230,14 +240,18 @@
     datum key, value;
     struct dbmdata *dbmp;
     DBM *dbm;
+    long len;
 
     ExportStringValue(keystr);
+    len = RSTRING_LEN(keystr);
+    if (TOO_LONG(len)) goto not_found;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (DSIZE_TYPE)len;
 
     GetDBM2(obj, dbmp, dbm);
     value = dbm_fetch(dbm, key);
     if (value.dptr == 0) {
+      not_found:
 	if (ifnone == Qnil && rb_block_given_p())
 	    return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
 	return ifnone;
@@ -291,15 +305,18 @@
     datum key, val;
     struct dbmdata *dbmp;
     DBM *dbm;
+    long len;
 
     ExportStringValue(valstr);
+    len = RSTRING_LEN(valstr);
+    if (TOO_LONG(len)) return Qnil;
     val.dptr = RSTRING_PTR(valstr);
-    val.dsize = (int)RSTRING_LEN(valstr);
+    val.dsize = (DSIZE_TYPE)len;
 
     GetDBM2(obj, dbmp, dbm);
     for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
 	val = dbm_fetch(dbm, key);
-	if ((long)val.dsize == (int)RSTRING_LEN(valstr) &&
+	if ((long)val.dsize == RSTRING_LEN(valstr) &&
 	    memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) {
 	    return rb_tainted_str_new(key.dptr, key.dsize);
 	}
@@ -385,16 +402,20 @@
     struct dbmdata *dbmp;
     DBM *dbm;
     VALUE valstr;
+    long len;
 
     fdbm_modify(obj);
     ExportStringValue(keystr);
+    len = RSTRING_LEN(keystr);
+    if (TOO_LONG(len)) goto not_found;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (DSIZE_TYPE)len;
 
     GetDBM2(obj, dbmp, dbm);
 
     value = dbm_fetch(dbm, key);
     if (value.dptr == 0) {
+      not_found:
 	if (rb_block_given_p()) return rb_yield(keystr);
 	return Qnil;
     }
@@ -457,7 +478,7 @@
     struct dbmdata *dbmp;
     DBM *dbm;
     VALUE keystr, valstr;
-    VALUE ret, ary = rb_ary_new();
+    VALUE ret, ary = rb_ary_tmp_new(0);
     int i, status = 0;
     long n;
 
@@ -469,6 +490,7 @@
     for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
 	val = dbm_fetch(dbm, key);
 	keystr = rb_tainted_str_new(key.dptr, key.dsize);
+	OBJ_FREEZE(keystr);
 	valstr = rb_tainted_str_new(val.dptr, val.dsize);
         ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
         if (status != 0) break;
@@ -478,15 +500,15 @@
 
     for (i = 0; i < RARRAY_LEN(ary); i++) {
 	keystr = RARRAY_PTR(ary)[i];
-	ExportStringValue(keystr);
 	key.dptr = RSTRING_PTR(keystr);
-	key.dsize = (int)RSTRING_LEN(keystr);
+	key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr);
 	if (dbm_delete(dbm, key)) {
 	    rb_raise(rb_eDBMError, "dbm_delete failed");
 	}
     }
     if (status) rb_jump_tag(status);
     if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
+    rb_ary_clear(ary);
 
     return obj;
 }
@@ -607,10 +629,10 @@
     valstr = rb_obj_as_string(valstr);
 
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = RSTRING_DSIZE(keystr);
 
     val.dptr = RSTRING_PTR(valstr);
-    val.dsize = (int)RSTRING_LEN(valstr);
+    val.dsize = RSTRING_DSIZE(valstr);
 
     GetDBM2(obj, dbmp, dbm);
     dbmp->di_size = -1;
@@ -816,10 +838,13 @@
     datum key, val;
     struct dbmdata *dbmp;
     DBM *dbm;
+    long len;
 
     ExportStringValue(keystr);
+    len = RSTRING_LEN(keystr);
+    if (TOO_LONG(len)) return Qfalse;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (DSIZE_TYPE)len;
 
     GetDBM2(obj, dbmp, dbm);
     val = dbm_fetch(dbm, key);
@@ -840,15 +865,18 @@
     datum key, val;
     struct dbmdata *dbmp;
     DBM *dbm;
+    long len;
 
     ExportStringValue(valstr);
+    len = RSTRING_LEN(valstr);
+    if (TOO_LONG(len)) return Qfalse;
     val.dptr = RSTRING_PTR(valstr);
-    val.dsize = (int)RSTRING_LEN(valstr);
+    val.dsize = (DSIZE_TYPE)len;
 
     GetDBM2(obj, dbmp, dbm);
     for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
 	val = dbm_fetch(dbm, key);
-	if (val.dsize == (int)RSTRING_LEN(valstr) &&
+	if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) &&
 	    memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
 	    return Qtrue;
     }
Index: ext/dbm/extconf.rb
===================================================================
--- ext/dbm/extconf.rb	(revision 33675)
+++ ext/dbm/extconf.rb	(revision 33676)
@@ -21,7 +21,10 @@
   "qdbm" => ["relic.h", "qdbm/relic.h"],
 }
 
-$dbm_headers = []
+class << headers
+  attr_accessor :found
+end
+headers.found = []
 
 def headers.db_check(db)
   db_prefix = nil
@@ -46,7 +49,7 @@
     have_func(db_prefix+"dbm_clearerr") unless have_gdbm
     $defs << hsearch if hsearch
     $defs << '-DDBM_HDR="<'+hdr+'>"'
-    $dbm_headers << hdr
+    @found << hdr
     true
   else
     false
@@ -56,7 +59,12 @@
 if dblib.any? {|db| headers.db_check(db)}
   have_header("cdefs.h")
   have_header("sys/cdefs.h")
-  have_func("dbm_pagfno", $dbm_headers)
-  have_func("dbm_dirfno", $dbm_headers)
+  have_func("dbm_pagfno", headers.found)
+  have_func("dbm_dirfno", headers.found)
+  if try_static_assert("sizeof(conftest_key.dsize) <= sizeof(int)", [[cpp_include(headers.found), "static datum conftest_key;"]])
+    $defs << "-DSIZEOF_DSIZE=SIZEOF_INT"
+  else
+    $defs << "-DSIZEOF_DSIZE=SIZEOF_LONG"
+  end
   create_makefile("dbm")
 end
Index: ext/gdbm/gdbm.c
===================================================================
--- ext/gdbm/gdbm.c	(revision 33675)
+++ ext/gdbm/gdbm.c	(revision 33676)
@@ -73,6 +73,12 @@
  */
 static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError;
 
+#if SIZEOF_LONG > SIZEOF_INT
+#define TOO_LONG(n) ((long)(+(int)(n)) != (long)(n))
+#else
+#define TOO_LONG(n) 0
+#endif
+
 #define RUBY_GDBM_RW_BIT 0x20000000
 
 #define MY_BLOCK_SIZE (2048)
@@ -301,10 +307,13 @@
 rb_gdbm_fetch2(GDBM_FILE dbm, VALUE keystr)
 {
     datum key;
+    long len;
 
     StringValue(keystr);
+    len = RSTRING_LEN(keystr);
+    if (TOO_LONG(len)) return Qnil;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (int)len;
 
     return rb_gdbm_fetch(dbm, key);
 }
@@ -340,9 +349,12 @@
 {
     datum key, key2;
     VALUE str;
+    long len;
 
+    len = RSTRING_LEN(keystr);
+    if (TOO_LONG(len)) return Qnil;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (int)len;
     key2 = gdbm_nextkey(dbm, key);
     if (key2.dptr == 0)
         return Qnil;
@@ -499,11 +511,14 @@
     datum key;
     struct dbmdata *dbmp;
     GDBM_FILE dbm;
+    long len;
 
     rb_gdbm_modify(obj);
     StringValue(keystr);
+    len = RSTRING_LEN(keystr);
+    if (TOO_LONG(len)) return Qnil;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (int)len;
 
     GetDBM2(obj, dbmp, dbm);
     if (!gdbm_exists(dbm, key)) {
@@ -574,7 +589,7 @@
     struct dbmdata *dbmp;
     GDBM_FILE dbm;
     VALUE keystr, valstr;
-    VALUE ret, ary = rb_ary_new();
+    VALUE ret, ary = rb_ary_tmp_new(0);
     int i, status = 0, n;
 
     rb_gdbm_modify(obj);
@@ -585,8 +600,9 @@
     for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
          keystr = rb_gdbm_nextkey(dbm, keystr)) {
 
+	OBJ_FREEZE(keystr);
         valstr = rb_gdbm_fetch2(dbm, keystr);
-        ret = rb_protect(rb_yield, rb_assoc_new(keystr, valstr), &status);
+        ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
         if (status != 0) break;
         if (RTEST(ret)) rb_ary_push(ary, keystr);
         GetDBM2(obj, dbmp, dbm);
@@ -596,6 +612,7 @@
         rb_gdbm_delete(obj, RARRAY_PTR(ary)[i]);
     if (status) rb_jump_tag(status);
     if (n > 0) dbmp->di_size = n - (int)RARRAY_LEN(ary);
+    rb_ary_clear(ary);
 
     return obj;
 }
@@ -687,10 +704,10 @@
     StringValue(valstr);
 
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = RSTRING_LENINT(keystr);
 
     val.dptr = RSTRING_PTR(valstr);
-    val.dsize = (int)RSTRING_LEN(valstr);
+    val.dsize = RSTRING_LENINT(valstr);
 
     GetDBM2(obj, dbmp, dbm);
     dbmp->di_size = -1;
@@ -943,10 +960,13 @@
     datum key;
     struct dbmdata *dbmp;
     GDBM_FILE dbm;
+    long len;
 
     StringValue(keystr);
+    len = RSTRING_LENINT(keystr);
+    if (TOO_LONG(len)) return Qfalse;
     key.dptr = RSTRING_PTR(keystr);
-    key.dsize = (int)RSTRING_LEN(keystr);
+    key.dsize = (int)len;
 
     GetDBM2(obj, dbmp, dbm);
     if (gdbm_exists(dbm, key))

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]