mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Check exception flag as a bool [Bug #15987]
This commit is contained in:
parent
cd069df365
commit
3e7d002118
12 changed files with 92 additions and 42 deletions
|
@ -477,13 +477,7 @@ nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
|
|||
a2 = Qundef;
|
||||
}
|
||||
if (!NIL_P(opts)) {
|
||||
static ID kwds[1];
|
||||
VALUE exception;
|
||||
if (!kwds[0]) {
|
||||
kwds[0] = idException;
|
||||
}
|
||||
rb_get_kwargs(opts, kwds, 0, 1, &exception);
|
||||
raise = (exception != Qfalse);
|
||||
raise = rb_opts_exception_p(opts, raise);
|
||||
}
|
||||
return nucomp_convert(rb_cComplex, a1, a2, raise);
|
||||
}
|
||||
|
|
|
@ -2560,6 +2560,10 @@ BigDecimal_clone(VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
#ifdef HAVE_RB_OPTS_EXCEPTION_P
|
||||
int rb_opts_exception_p(VALUE opts, int default_value);
|
||||
#define opts_exception_p(opts) rb_opts_exception_p((opts), 1)
|
||||
#else
|
||||
static int
|
||||
opts_exception_p(VALUE opts)
|
||||
{
|
||||
|
@ -2569,8 +2573,16 @@ opts_exception_p(VALUE opts)
|
|||
kwds[0] = rb_intern_const("exception");
|
||||
}
|
||||
rb_get_kwargs(opts, kwds, 0, 1, &exception);
|
||||
switch (exception) {
|
||||
case Qtrue: case Qfalse:
|
||||
break;
|
||||
default:
|
||||
rb_raise(rb_eArgError, "true or false is expected as exception: %+"PRIsVALUE,
|
||||
flagname, obj);
|
||||
}
|
||||
return exception != Qfalse;
|
||||
}
|
||||
#endif
|
||||
|
||||
static Real *
|
||||
BigDecimal_new(int argc, VALUE *argv)
|
||||
|
|
|
@ -27,6 +27,7 @@ have_func("rb_rational_num", "ruby.h")
|
|||
have_func("rb_rational_den", "ruby.h")
|
||||
have_func("rb_array_const_ptr", "ruby.h")
|
||||
have_func("rb_sym2str", "ruby.h")
|
||||
have_func("rb_opts_exception_p", "ruby.h")
|
||||
|
||||
if File.file?(File.expand_path('../lib/bigdecimal.rb', __FILE__))
|
||||
bigdecimal_rb = "$(srcdir)/lib/bigdecimal.rb"
|
||||
|
|
|
@ -1891,6 +1891,7 @@ VALUE rb_immutable_obj_clone(int, VALUE *, VALUE);
|
|||
VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
|
||||
VALUE rb_convert_type_with_id(VALUE,int,const char*,ID);
|
||||
VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID);
|
||||
int rb_bool_expected(VALUE, const char *);
|
||||
|
||||
struct RBasicRaw {
|
||||
VALUE flags;
|
||||
|
@ -2349,6 +2350,9 @@ void rb_write_error_str(VALUE mesg);
|
|||
/* numeric.c (export) */
|
||||
VALUE rb_int_positive_pow(long x, unsigned long y);
|
||||
|
||||
/* object.c (export) */
|
||||
int rb_opts_exception_p(VALUE opts, int default_value);
|
||||
|
||||
/* process.c (export) */
|
||||
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen);
|
||||
rb_pid_t rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen);
|
||||
|
|
36
io.c
36
io.c
|
@ -171,7 +171,6 @@ VALUE rb_default_rs;
|
|||
|
||||
static VALUE argf;
|
||||
|
||||
#define id_exception idException
|
||||
static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
|
||||
static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
|
||||
static VALUE sym_textmode, sym_binmode, sym_autoclose;
|
||||
|
@ -2793,18 +2792,10 @@ read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
|
|||
return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
|
||||
}
|
||||
|
||||
static int
|
||||
no_exception_p(VALUE opts)
|
||||
{
|
||||
VALUE except;
|
||||
ID id = id_exception;
|
||||
|
||||
rb_get_kwargs(opts, &id, 0, 1, &except);
|
||||
return except == Qfalse;
|
||||
}
|
||||
#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
|
||||
|
||||
static VALUE
|
||||
io_getpartial(int argc, VALUE *argv, VALUE io, VALUE opts, int nonblock)
|
||||
io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
|
||||
{
|
||||
rb_io_t *fptr;
|
||||
VALUE length, str;
|
||||
|
@ -2846,7 +2837,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, VALUE opts, int nonblock)
|
|||
if (!nonblock && fptr_wait_readable(fptr))
|
||||
goto again;
|
||||
if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
|
||||
if (no_exception_p(opts))
|
||||
if (no_exception)
|
||||
return sym_wait_readable;
|
||||
else
|
||||
rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
|
||||
|
@ -2940,9 +2931,9 @@ io_readpartial(int argc, VALUE *argv, VALUE io)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
io_nonblock_eof(VALUE opts)
|
||||
io_nonblock_eof(int no_exception)
|
||||
{
|
||||
if (!no_exception_p(opts)) {
|
||||
if (!no_exception) {
|
||||
rb_eof_error();
|
||||
}
|
||||
return Qnil;
|
||||
|
@ -2963,6 +2954,8 @@ io_read_nonblock(VALUE io, VALUE length, VALUE str, VALUE ex)
|
|||
|
||||
shrinkable = io_setstrbuf(&str, len);
|
||||
OBJ_TAINT(str);
|
||||
rb_bool_expected(ex, "exception");
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
|
||||
|
@ -2981,7 +2974,7 @@ io_read_nonblock(VALUE io, VALUE length, VALUE str, VALUE ex)
|
|||
if (n < 0) {
|
||||
int e = errno;
|
||||
if ((e == EWOULDBLOCK || e == EAGAIN)) {
|
||||
if (ex == Qfalse) return sym_wait_readable;
|
||||
if (!ex) return sym_wait_readable;
|
||||
rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
|
||||
e, "read would block");
|
||||
}
|
||||
|
@ -2991,7 +2984,7 @@ io_read_nonblock(VALUE io, VALUE length, VALUE str, VALUE ex)
|
|||
io_set_read_length(str, n, shrinkable);
|
||||
|
||||
if (n == 0) {
|
||||
if (ex == Qfalse) return Qnil;
|
||||
if (!ex) return Qnil;
|
||||
rb_eof_error();
|
||||
}
|
||||
|
||||
|
@ -3007,6 +3000,7 @@ io_write_nonblock(VALUE io, VALUE str, VALUE ex)
|
|||
|
||||
if (!RB_TYPE_P(str, T_STRING))
|
||||
str = rb_obj_as_string(str);
|
||||
rb_bool_expected(ex, "exception");
|
||||
|
||||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
|
@ -3022,7 +3016,7 @@ io_write_nonblock(VALUE io, VALUE str, VALUE ex)
|
|||
if (n < 0) {
|
||||
int e = errno;
|
||||
if (e == EWOULDBLOCK || e == EAGAIN) {
|
||||
if (ex == Qfalse) {
|
||||
if (!ex) {
|
||||
return sym_wait_writable;
|
||||
}
|
||||
else {
|
||||
|
@ -12193,12 +12187,14 @@ static VALUE
|
|||
argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
|
||||
{
|
||||
VALUE tmp, str, length;
|
||||
int no_exception;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &length, &str);
|
||||
if (!NIL_P(str)) {
|
||||
StringValue(str);
|
||||
argv[1] = str;
|
||||
}
|
||||
no_exception = no_exception_p(opts);
|
||||
|
||||
if (!next_argv()) {
|
||||
if (!NIL_P(str)) {
|
||||
|
@ -12215,16 +12211,16 @@ argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
|
|||
RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
|
||||
}
|
||||
else {
|
||||
tmp = io_getpartial(argc, argv, ARGF.current_file, opts, nonblock);
|
||||
tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
|
||||
}
|
||||
if (NIL_P(tmp)) {
|
||||
if (ARGF.next_p == -1) {
|
||||
return io_nonblock_eof(opts);
|
||||
return io_nonblock_eof(no_exception);
|
||||
}
|
||||
argf_close(argf);
|
||||
ARGF.next_p = 1;
|
||||
if (RARRAY_LEN(ARGF.argv) == 0) {
|
||||
return io_nonblock_eof(opts);
|
||||
return io_nonblock_eof(no_exception);
|
||||
}
|
||||
if (NIL_P(str))
|
||||
str = rb_str_new(NULL, 0);
|
||||
|
|
29
object.c
29
object.c
|
@ -3330,18 +3330,31 @@ rb_Integer(VALUE val)
|
|||
return rb_convert_to_integer(val, 0, TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
opts_exception_p(VALUE opts)
|
||||
int
|
||||
rb_bool_expected(VALUE obj, const char *flagname)
|
||||
{
|
||||
static ID kwds[1];
|
||||
VALUE exception;
|
||||
if (!kwds[0]) {
|
||||
kwds[0] = idException;
|
||||
switch (obj) {
|
||||
case Qtrue: case Qfalse:
|
||||
break;
|
||||
default:
|
||||
rb_raise(rb_eArgError, "true or false is expected as %s: %+"PRIsVALUE,
|
||||
flagname, obj);
|
||||
}
|
||||
rb_get_kwargs(opts, kwds, 0, 1, &exception);
|
||||
return exception != Qfalse;
|
||||
return obj != Qfalse;
|
||||
}
|
||||
|
||||
int
|
||||
rb_opts_exception_p(VALUE opts, int default_value)
|
||||
{
|
||||
static ID kwds[1] = {idException};
|
||||
VALUE exception;
|
||||
if (rb_get_kwargs(opts, kwds, 0, 1, &exception))
|
||||
return rb_bool_expected(exception, "exception");
|
||||
return default_value;
|
||||
}
|
||||
|
||||
#define opts_exception_p(opts) rb_opts_exception_p((opts), TRUE)
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Integer(arg, base=0, exception: true) -> integer or nil
|
||||
|
|
|
@ -574,13 +574,7 @@ nurat_f_rational(int argc, VALUE *argv, VALUE klass)
|
|||
a2 = Qundef;
|
||||
}
|
||||
if (!NIL_P(opts)) {
|
||||
static ID kwds[1];
|
||||
VALUE exception;
|
||||
if (!kwds[0]) {
|
||||
kwds[0] = idException;
|
||||
}
|
||||
rb_get_kwargs(opts, kwds, 0, 1, &exception);
|
||||
raise = (exception != Qfalse);
|
||||
raise = rb_opts_exception_p(opts, raise);
|
||||
}
|
||||
return nurat_convert(rb_cRational, a1, a2, raise);
|
||||
}
|
||||
|
|
|
@ -868,6 +868,12 @@ class Complex_Test < Test::Unit::TestCase
|
|||
|
||||
end
|
||||
|
||||
def test_Complex_with_invalid_exception
|
||||
assert_raise(ArgumentError) {
|
||||
Complex("0", exception: 1)
|
||||
}
|
||||
end
|
||||
|
||||
def test_Complex_without_exception
|
||||
assert_nothing_raised(ArgumentError){
|
||||
assert_equal(nil, Complex('5x', exception: false))
|
||||
|
|
|
@ -802,6 +802,12 @@ class TestFloat < Test::Unit::TestCase
|
|||
assert_raise(ArgumentError, bug4310) {under_gc_stress {Float('a'*10000)}}
|
||||
end
|
||||
|
||||
def test_Float_with_invalid_exception
|
||||
assert_raise(ArgumentError) {
|
||||
Float("0", exception: 1)
|
||||
}
|
||||
end
|
||||
|
||||
def test_Float_with_exception_keyword
|
||||
assert_raise(ArgumentError) {
|
||||
Float(".", exception: true)
|
||||
|
|
|
@ -192,6 +192,12 @@ class TestInteger < Test::Unit::TestCase
|
|||
end;
|
||||
end
|
||||
|
||||
def test_Integer_with_exception_keyword
|
||||
assert_raise(ArgumentError) {
|
||||
Integer("0", exception: 1)
|
||||
}
|
||||
end
|
||||
|
||||
def test_Integer_with_exception_keyword
|
||||
assert_nothing_raised(ArgumentError) {
|
||||
assert_equal(nil, Integer("1z", exception: false))
|
||||
|
|
|
@ -1509,6 +1509,12 @@ class TestIO < Test::Unit::TestCase
|
|||
}
|
||||
end if have_nonblock?
|
||||
|
||||
def test_read_nonblock_invalid_exception
|
||||
with_pipe {|r, w|
|
||||
assert_raise(ArgumentError) {r.read_nonblock(4096, exception: 1)}
|
||||
}
|
||||
end if have_nonblock?
|
||||
|
||||
def test_read_nonblock_no_exceptions
|
||||
skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker.
|
||||
with_pipe {|r, w|
|
||||
|
@ -1545,6 +1551,12 @@ class TestIO < Test::Unit::TestCase
|
|||
}
|
||||
end if have_nonblock?
|
||||
|
||||
def test_write_nonblock_invalid_exception
|
||||
with_pipe {|r, w|
|
||||
assert_raise(ArgumentError) {w.write_nonblock(4096, exception: 1)}
|
||||
}
|
||||
end if have_nonblock?
|
||||
|
||||
def test_write_nonblock_no_exceptions
|
||||
with_pipe {|r, w|
|
||||
loop {
|
||||
|
|
|
@ -808,6 +808,12 @@ class Rational_Test < Test::Unit::TestCase
|
|||
assert_raise(ZeroDivisionError) {Rational("1/0")}
|
||||
end
|
||||
|
||||
def test_Rational_with_invalid_exception
|
||||
assert_raise(ArgumentError) {
|
||||
Rational("1/1", exception: 1)
|
||||
}
|
||||
end
|
||||
|
||||
def test_Rational_without_exception
|
||||
assert_nothing_raised(ArgumentError) {
|
||||
assert_equal(nil, Rational("5/3x", exception: false))
|
||||
|
|
Loading…
Reference in a new issue