Skip to content

Commit

Permalink
Add arity-checking anywhere it is missing (#48)
Browse files Browse the repository at this point in the history
As part of jruby/jruby#7751 we are recommending that all extension code
manually check the arity of incoming arguments to variable- arity
methods, as in CRuby. This ensures that all call paths will be checked,
including direct paths from Java or invokedynamic, and avoids array
indexing errors in these situations.
  • Loading branch information
headius authored Apr 12, 2023
1 parent f0bf36b commit 06ceff7
Showing 1 changed file with 17 additions and 5 deletions.
22 changes: 17 additions & 5 deletions ext/java/org/jruby/ext/stringio/StringIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ protected StringIO(Ruby runtime, RubyClass klass) {

@JRubyMethod(optional = 2, visibility = PRIVATE)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
Arity.checkArgumentCount(context, args, 0, 2);

if (ptr == null) {
ptr = new StringIOData();
}
Expand Down Expand Up @@ -865,7 +867,7 @@ public IRubyObject read(ThreadContext context, IRubyObject[] args) {
}
break;
default:
throw runtime.newArgumentError(args.length, 0);
throw runtime.newArgumentError(args.length, 0, 2);
}

if (str.isNil()) {
Expand Down Expand Up @@ -930,11 +932,13 @@ public IRubyObject readlines(ThreadContext context, IRubyObject[] args) {
}

// MRI: strio_reopen
@JRubyMethod(name = "reopen", required = 0, optional = 2)
@JRubyMethod(name = "reopen", optional = 2)
public IRubyObject reopen(ThreadContext context, IRubyObject[] args) {
int argc = Arity.checkArgumentCount(context, args, 0, 2);

checkFrozen();

if (args.length == 1 && !(args[0] instanceof RubyString)) {
if (argc == 1 && !(args[0] instanceof RubyString)) {
return initialize_copy(context, args[0]);
}

Expand All @@ -959,6 +963,8 @@ public IRubyObject rewind(ThreadContext context) {

@JRubyMethod(required = 1, optional = 1)
public IRubyObject seek(ThreadContext context, IRubyObject[] args) {
int argc = Arity.checkArgumentCount(context, args, 1, 2);

Ruby runtime = context.runtime;

checkFrozen();
Expand All @@ -967,7 +973,7 @@ public IRubyObject seek(ThreadContext context, IRubyObject[] args) {
int offset = RubyNumeric.num2int(args[0]);
IRubyObject whence = context.nil;

if (args.length > 1 && !args[0].isNil()) whence = args[1];
if (argc > 1 && !args[0].isNil()) whence = args[1];

checkOpen();

Expand Down Expand Up @@ -1163,6 +1169,8 @@ public IRubyObject write(ThreadContext context, IRubyObject arg) {

@JRubyMethod(name = "write", required = 1, rest = true)
public IRubyObject write(ThreadContext context, IRubyObject[] args) {
Arity.checkArgumentCount(context, args, 1, -1);

Ruby runtime = context.runtime;
long len = 0;
for (IRubyObject arg : args) {
Expand Down Expand Up @@ -1333,12 +1341,14 @@ public static IRubyObject sysread(ThreadContext context, IRubyObject self, IRuby

@JRubyMethod(name = "read_nonblock", required = 1, optional = 2)
public static IRubyObject read_nonblock(ThreadContext context, IRubyObject self, IRubyObject[] args) {
int argc = Arity.checkArgumentCount(context, args, 1, 3);

final Ruby runtime = context.runtime;

boolean exception = true;
IRubyObject opts = ArgsUtil.getOptionsArg(runtime, args);
if (opts != context.nil) {
args = ArraySupport.newCopy(args, args.length - 1);
args = ArraySupport.newCopy(args, argc - 1);
exception = Helpers.extractExceptionOnlyArg(context, (RubyHash) opts);
}

Expand Down Expand Up @@ -1431,6 +1441,8 @@ public static IRubyObject syswrite(ThreadContext context, IRubyObject self, IRub

@JRubyMethod(name = "write_nonblock", required = 1, optional = 1)
public static IRubyObject syswrite_nonblock(ThreadContext context, IRubyObject self, IRubyObject[] args) {
Arity.checkArgumentCount(context, args, 1, 2);

Ruby runtime = context.runtime;

ArgsUtil.getOptionsArg(runtime, args); // ignored as in MRI
Expand Down

0 comments on commit 06ceff7

Please sign in to comment.