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/