mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
-This line, and those below, will be ignored--
M ruby_1_8_7/ChangeLog M ruby_1_8_7/inits.c M ruby_1_8_7/version.h M ruby_1_8_7/string.c M ruby_1_8_7/st.c M ruby_1_8_7/test/ruby/test_string.rb M ruby_1_8_7/random.c git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@34151 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
858cb3f6b9
commit
e19bd3eaa8
7 changed files with 123 additions and 23 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
||||||
|
Wed Dec 28 21:34:23 2011 URABE Shyouhei <shyouhei@ruby-lang.org>
|
||||||
|
|
||||||
|
* string.c (rb_str_hash): randomize hash to avoid algorithmic
|
||||||
|
complexity attacks. CVE-2011-4815
|
||||||
|
|
||||||
|
* st.c (strhash): ditto.
|
||||||
|
|
||||||
|
* string.c (Init_String): initialization of hash_seed to be at the
|
||||||
|
beginning of the process.
|
||||||
|
|
||||||
|
* st.c (Init_st): ditto.
|
||||||
|
|
||||||
|
Thu Dec 8 11:57:04 2011 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* inits.c (rb_call_inits): call Init_RandomSeed at first.
|
||||||
|
|
||||||
|
* random.c (seed_initialized): defined.
|
||||||
|
(fill_random_seed): extracted from random_seed.
|
||||||
|
(make_seed_value): extracted from random_seed.
|
||||||
|
(rb_f_rand): initialize random seed at first.
|
||||||
|
(initial_seed): defined.
|
||||||
|
(Init_RandomSeed): defined.
|
||||||
|
(Init_RandomSeed2): defined.
|
||||||
|
(rb_reset_random_seed): defined.
|
||||||
|
(Init_Random): call Init_RandomSeed2.
|
||||||
|
|
||||||
Sat Dec 10 20:44:23 2011 Tanaka Akira <akr@fsij.org>
|
Sat Dec 10 20:44:23 2011 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* lib/securerandom.rb: call OpenSSL::Random.seed at the
|
* lib/securerandom.rb: call OpenSSL::Random.seed at the
|
||||||
|
|
4
inits.c
4
inits.c
|
@ -38,6 +38,7 @@ void Init_Precision _((void));
|
||||||
void Init_sym _((void));
|
void Init_sym _((void));
|
||||||
void Init_process _((void));
|
void Init_process _((void));
|
||||||
void Init_Random _((void));
|
void Init_Random _((void));
|
||||||
|
void Init_RandomSeed _((void));
|
||||||
void Init_Range _((void));
|
void Init_Range _((void));
|
||||||
void Init_Regexp _((void));
|
void Init_Regexp _((void));
|
||||||
void Init_signal _((void));
|
void Init_signal _((void));
|
||||||
|
@ -46,10 +47,13 @@ void Init_Struct _((void));
|
||||||
void Init_Time _((void));
|
void Init_Time _((void));
|
||||||
void Init_var_tables _((void));
|
void Init_var_tables _((void));
|
||||||
void Init_version _((void));
|
void Init_version _((void));
|
||||||
|
void Init_st _((void));
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_call_inits()
|
rb_call_inits()
|
||||||
{
|
{
|
||||||
|
Init_RandomSeed();
|
||||||
|
Init_st();
|
||||||
Init_sym();
|
Init_sym();
|
||||||
Init_var_tables();
|
Init_var_tables();
|
||||||
Init_Object();
|
Init_Object();
|
||||||
|
|
74
random.c
74
random.c
|
@ -189,6 +189,7 @@ rb_genrand_real(void)
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int seed_initialized = 0;
|
||||||
static VALUE saved_seed = INT2FIX(0);
|
static VALUE saved_seed = INT2FIX(0);
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -250,27 +251,22 @@ rand_init(vseed)
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
#define DEFAULT_SEED_LEN (4 * sizeof(long))
|
||||||
random_seed()
|
|
||||||
|
static void
|
||||||
|
fill_random_seed(ptr)
|
||||||
|
char *ptr;
|
||||||
{
|
{
|
||||||
static int n = 0;
|
static int n = 0;
|
||||||
|
unsigned long *seed;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int fd;
|
int fd;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
char *buf = (char*)ptr;
|
||||||
|
|
||||||
int seed_len;
|
seed = (unsigned long *)buf;
|
||||||
BDIGIT *digits;
|
|
||||||
unsigned long *seed;
|
|
||||||
NEWOBJ(big, struct RBignum);
|
|
||||||
OBJSETUP(big, rb_cBignum, T_BIGNUM);
|
|
||||||
|
|
||||||
seed_len = 4 * sizeof(long);
|
memset(buf, 0, DEFAULT_SEED_LEN);
|
||||||
big->sign = 1;
|
|
||||||
big->len = seed_len / SIZEOF_BDIGITS + 1;
|
|
||||||
digits = big->digits = ALLOC_N(BDIGIT, big->len);
|
|
||||||
seed = (unsigned long *)big->digits;
|
|
||||||
|
|
||||||
memset(digits, 0, big->len * SIZEOF_BDIGITS);
|
|
||||||
|
|
||||||
#ifdef S_ISCHR
|
#ifdef S_ISCHR
|
||||||
if ((fd = open("/dev/urandom", O_RDONLY
|
if ((fd = open("/dev/urandom", O_RDONLY
|
||||||
|
@ -285,7 +281,7 @@ random_seed()
|
||||||
#endif
|
#endif
|
||||||
)) >= 0) {
|
)) >= 0) {
|
||||||
if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
|
if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
|
||||||
read(fd, seed, seed_len);
|
read(fd, seed, DEFAULT_SEED_LEN);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
@ -296,13 +292,37 @@ random_seed()
|
||||||
seed[1] ^= tv.tv_sec;
|
seed[1] ^= tv.tv_sec;
|
||||||
seed[2] ^= getpid() ^ (n++ << 16);
|
seed[2] ^= getpid() ^ (n++ << 16);
|
||||||
seed[3] ^= (unsigned long)&seed;
|
seed[3] ^= (unsigned long)&seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
make_seed_value(char *ptr)
|
||||||
|
{
|
||||||
|
BDIGIT *digits;
|
||||||
|
NEWOBJ(big, struct RBignum);
|
||||||
|
OBJSETUP(big, rb_cBignum, T_BIGNUM);
|
||||||
|
|
||||||
|
RBIGNUM_SET_SIGN(big, 1);
|
||||||
|
|
||||||
|
digits = ALLOC_N(char, DEFAULT_SEED_LEN);
|
||||||
|
RBIGNUM(big)->digits = digits;
|
||||||
|
RBIGNUM(big)->len = DEFAULT_SEED_LEN / SIZEOF_BDIGITS;
|
||||||
|
|
||||||
|
MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN);
|
||||||
|
|
||||||
/* set leading-zero-guard if need. */
|
/* set leading-zero-guard if need. */
|
||||||
digits[big->len-1] = digits[big->len-2] <= 1 ? 1 : 0;
|
digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0;
|
||||||
|
|
||||||
return rb_big_norm((VALUE)big);
|
return rb_big_norm((VALUE)big);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
random_seed(void)
|
||||||
|
{
|
||||||
|
char buf[DEFAULT_SEED_LEN];
|
||||||
|
fill_random_seed(buf);
|
||||||
|
return make_seed_value(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* srand(number=0) => old_seed
|
* srand(number=0) => old_seed
|
||||||
|
@ -443,6 +463,9 @@ rb_f_rand(argc, argv, obj)
|
||||||
long val, max;
|
long val, max;
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "01", &vmax);
|
rb_scan_args(argc, argv, "01", &vmax);
|
||||||
|
if (!seed_initialized) {
|
||||||
|
rand_init(random_seed());
|
||||||
|
}
|
||||||
switch (TYPE(vmax)) {
|
switch (TYPE(vmax)) {
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
if (RFLOAT(vmax)->value <= LONG_MAX && RFLOAT(vmax)->value >= LONG_MIN) {
|
if (RFLOAT(vmax)->value <= LONG_MAX && RFLOAT(vmax)->value >= LONG_MIN) {
|
||||||
|
@ -490,16 +513,33 @@ rb_f_rand(argc, argv, obj)
|
||||||
return LONG2NUM(val);
|
return LONG2NUM(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char initial_seed[DEFAULT_SEED_LEN];
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_reset_random_seed()
|
rb_reset_random_seed()
|
||||||
{
|
{
|
||||||
rand_init(random_seed());
|
rand_init(random_seed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_RandomSeed(void)
|
||||||
|
{
|
||||||
|
fill_random_seed(initial_seed);
|
||||||
|
init_by_array((unsigned long*)initial_seed, DEFAULT_SEED_LEN/sizeof(unsigned long));
|
||||||
|
seed_initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Init_RandomSeed2(void)
|
||||||
|
{
|
||||||
|
saved_seed = make_seed_value(initial_seed);
|
||||||
|
memset(initial_seed, 0, DEFAULT_SEED_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_Random()
|
Init_Random()
|
||||||
{
|
{
|
||||||
rb_reset_random_seed();
|
Init_RandomSeed2();
|
||||||
rb_define_global_function("srand", rb_f_srand, -1);
|
rb_define_global_function("srand", rb_f_srand, -1);
|
||||||
rb_define_global_function("rand", rb_f_rand, -1);
|
rb_define_global_function("rand", rb_f_rand, -1);
|
||||||
rb_global_variable(&saved_seed);
|
rb_global_variable(&saved_seed);
|
||||||
|
|
14
st.c
14
st.c
|
@ -9,6 +9,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
#include "st.h"
|
#include "st.h"
|
||||||
|
|
||||||
typedef struct st_table_entry st_table_entry;
|
typedef struct st_table_entry st_table_entry;
|
||||||
|
@ -521,6 +522,8 @@ st_foreach(table, func, arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long hash_seed = 0;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
strhash(string)
|
strhash(string)
|
||||||
register const char *string;
|
register const char *string;
|
||||||
|
@ -550,10 +553,11 @@ strhash(string)
|
||||||
|
|
||||||
return val + (val << 15);
|
return val + (val << 15);
|
||||||
#else
|
#else
|
||||||
register int val = 0;
|
register unsigned long val = hash_seed;
|
||||||
|
|
||||||
while ((c = *string++) != '\0') {
|
while ((c = *string++) != '\0') {
|
||||||
val = val*997 + c;
|
val = val*997 + c;
|
||||||
|
val = (val << 13) | (val >> (sizeof(st_data_t) * CHAR_BIT - 13));
|
||||||
}
|
}
|
||||||
|
|
||||||
return val + (val>>5);
|
return val + (val>>5);
|
||||||
|
@ -573,3 +577,11 @@ numhash(n)
|
||||||
{
|
{
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern unsigned long rb_genrand_int32(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_st(void)
|
||||||
|
{
|
||||||
|
hash_seed = rb_genrand_int32();
|
||||||
|
}
|
||||||
|
|
7
string.c
7
string.c
|
@ -875,13 +875,15 @@ rb_str_concat(str1, str2)
|
||||||
return str1;
|
return str1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long hash_seed;
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_str_hash(str)
|
rb_str_hash(str)
|
||||||
VALUE str;
|
VALUE str;
|
||||||
{
|
{
|
||||||
register long len = RSTRING(str)->len;
|
register long len = RSTRING(str)->len;
|
||||||
register char *p = RSTRING(str)->ptr;
|
register char *p = RSTRING(str)->ptr;
|
||||||
register int key = 0;
|
register unsigned long key = hash_seed;
|
||||||
|
|
||||||
#if defined(HASH_ELFHASH)
|
#if defined(HASH_ELFHASH)
|
||||||
register unsigned int g;
|
register unsigned int g;
|
||||||
|
@ -905,6 +907,7 @@ rb_str_hash(str)
|
||||||
while (len--) {
|
while (len--) {
|
||||||
key = key*65599 + *p;
|
key = key*65599 + *p;
|
||||||
p++;
|
p++;
|
||||||
|
key = (key << 13) | (key >> ((sizeof(unsigned long) * CHAR_BIT) - 13));
|
||||||
}
|
}
|
||||||
key = key + (key>>5);
|
key = key + (key>>5);
|
||||||
#endif
|
#endif
|
||||||
|
@ -5062,4 +5065,6 @@ Init_String()
|
||||||
rb_fs = Qnil;
|
rb_fs = Qnil;
|
||||||
rb_define_variable("$;", &rb_fs);
|
rb_define_variable("$;", &rb_fs);
|
||||||
rb_define_variable("$-F", &rb_fs);
|
rb_define_variable("$-F", &rb_fs);
|
||||||
|
|
||||||
|
hash_seed = rb_genrand_int32();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
|
require File.expand_path('envutil', File.dirname(__FILE__))
|
||||||
|
|
||||||
class TestString < Test::Unit::TestCase
|
class TestString < Test::Unit::TestCase
|
||||||
def check_sum(str, bits=16)
|
def check_sum(str, bits=16)
|
||||||
|
@ -29,4 +30,16 @@ class TestString < Test::Unit::TestCase
|
||||||
ensure
|
ensure
|
||||||
$KCODE = original_kcode
|
$KCODE = original_kcode
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_hash_random
|
||||||
|
str = 'abc'
|
||||||
|
a = [str.hash.to_s]
|
||||||
|
cmd = sprintf("%s -e 'print %s.hash'", EnvUtil.rubybin, str.dump)
|
||||||
|
3.times {
|
||||||
|
IO.popen(cmd, "rb") {|o|
|
||||||
|
a << o.read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_not_equal([str.hash.to_s], a.uniq)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
#define RUBY_VERSION "1.8.7"
|
#define RUBY_VERSION "1.8.7"
|
||||||
#define RUBY_RELEASE_DATE "2011-12-10"
|
#define RUBY_RELEASE_DATE "2011-12-28"
|
||||||
#define RUBY_VERSION_CODE 187
|
#define RUBY_VERSION_CODE 187
|
||||||
#define RUBY_RELEASE_CODE 20111210
|
#define RUBY_RELEASE_CODE 20111228
|
||||||
#define RUBY_PATCHLEVEL 356
|
#define RUBY_PATCHLEVEL 357
|
||||||
|
|
||||||
#define RUBY_VERSION_MAJOR 1
|
#define RUBY_VERSION_MAJOR 1
|
||||||
#define RUBY_VERSION_MINOR 8
|
#define RUBY_VERSION_MINOR 8
|
||||||
#define RUBY_VERSION_TEENY 7
|
#define RUBY_VERSION_TEENY 7
|
||||||
#define RUBY_RELEASE_YEAR 2011
|
#define RUBY_RELEASE_YEAR 2011
|
||||||
#define RUBY_RELEASE_MONTH 12
|
#define RUBY_RELEASE_MONTH 12
|
||||||
#define RUBY_RELEASE_DAY 10
|
#define RUBY_RELEASE_DAY 28
|
||||||
|
|
||||||
#ifdef RUBY_EXTERN
|
#ifdef RUBY_EXTERN
|
||||||
RUBY_EXTERN const char ruby_version[];
|
RUBY_EXTERN const char ruby_version[];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue