mirror of
https://github.com/ruby/ruby.git
synced 2026-11-08 01:20:26 +08:00
Use rb_len_t for byte lengths in random.c
Random.urandom converts its size with NUM2LEN instead of the unsigned macro, so a negative Integer raises ArgumentError without wrapping through the whole unsigned range first, and a size beyond the signed range raises RangeError the way Random#bytes already does. Neither error was covered before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
94f16320f7
commit
fa1bbf4163
Notes:
git
2026-10-09 05:02:04 +00:00
18
random.c
18
random.c
@ -726,7 +726,7 @@ random_seed(VALUE _)
|
||||
static VALUE
|
||||
random_raw_seed(VALUE self, VALUE size)
|
||||
{
|
||||
long n = NUM2ULONG(size);
|
||||
rb_len_t n = NUM2LEN(size);
|
||||
VALUE buf = rb_str_new(0, n);
|
||||
if (n == 0) return buf;
|
||||
if (fill_random_bytes(RSTRING_PTR(buf), n, TRUE))
|
||||
@ -1036,17 +1036,17 @@ rb_genrand_ulong_limited(unsigned long limit)
|
||||
}
|
||||
|
||||
static VALUE
|
||||
obj_random_bytes(VALUE obj, void *p, long n)
|
||||
obj_random_bytes(VALUE obj, void *p, rb_len_t n)
|
||||
{
|
||||
VALUE len = LONG2NUM(n);
|
||||
VALUE len = LEN2NUM(n);
|
||||
VALUE v = rb_funcallv_public(obj, id_bytes, 1, &len);
|
||||
long l;
|
||||
rb_len_t l;
|
||||
Check_Type(v, T_STRING);
|
||||
l = RSTRING_LEN(v);
|
||||
if (l < n)
|
||||
rb_raise(rb_eRangeError, "random data too short %ld", l);
|
||||
rb_raise(rb_eRangeError, "random data too short %"PRIdLEN, l);
|
||||
else if (l > n)
|
||||
rb_raise(rb_eRangeError, "random data too long %ld", l);
|
||||
rb_raise(rb_eRangeError, "random data too long %"PRIdLEN, l);
|
||||
if (p) memcpy(p, RSTRING_PTR(v), n);
|
||||
return v;
|
||||
}
|
||||
@ -1211,7 +1211,7 @@ random_ulong_limited_big(VALUE obj, const rb_random_interface_t *rng, rb_random_
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, long n)
|
||||
rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, rb_len_t n)
|
||||
{
|
||||
VALUE bytes;
|
||||
char *ptr;
|
||||
@ -1235,7 +1235,7 @@ random_bytes(VALUE obj, VALUE len)
|
||||
{
|
||||
const rb_random_interface_t *rng = NULL;
|
||||
rb_random_t *rnd = try_get_rnd(obj, &rng);
|
||||
return rand_bytes(rng, rnd, NUM2LONG(rb_to_int(len)));
|
||||
return rand_bytes(rng, rnd, NUM2LEN(rb_to_int(len)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1282,7 +1282,7 @@ static VALUE
|
||||
random_s_bytes(VALUE obj, VALUE len)
|
||||
{
|
||||
rb_random_t *rnd = default_rand_start();
|
||||
return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
|
||||
return rand_bytes(&random_mt_if, rnd, NUM2LEN(rb_to_int(len)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
# frozen_string_literal: false
|
||||
require 'test/unit'
|
||||
require 'rbconfig/sizeof'
|
||||
|
||||
class TestRand < Test::Unit::TestCase
|
||||
def assert_random_int(m, init = 0, iterate: 5)
|
||||
@ -423,6 +424,15 @@ class TestRand < Test::Unit::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
def test_urandom_size_errors
|
||||
beyond_long = 2 ** (RbConfig::SIZEOF['long'] * 8 - 1)
|
||||
assert_raise(ArgumentError) { Random.urandom(-1) }
|
||||
assert_raise(RangeError) { Random.urandom(beyond_long) }
|
||||
# Random#bytes converts its size the same way, so the classes have to agree
|
||||
assert_raise(ArgumentError) { Random.new.bytes(-1) }
|
||||
assert_raise(RangeError) { Random.new.bytes(beyond_long) }
|
||||
end
|
||||
|
||||
def test_new_seed
|
||||
size = 0
|
||||
n = 8
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user