Skip to content

Commit

Permalink
Fixes #3680. JRuby and devise Null pointer exception
Browse files Browse the repository at this point in the history
This was largely just some code which was added before prepend existed.
It would re-wrap begin and end of a range and make an array and call min
on that.  This would obviously not have anything prepended on it and it
would not even be the same type.

I ended up re-porting min and max in range from MRI since I found another
mistake with min(a) and max(a) not passing a to super if invoked in the
block form.  This also makes us a tiny bit faster since we end up only
doing on cmp in cases of fixnums (why is this even optimized by MRI :) ).
enebo committed May 12, 2016
1 parent 9334a2b commit d0fe3c0
Showing 2 changed files with 23 additions and 36 deletions.
58 changes: 23 additions & 35 deletions core/src/main/java/org/jruby/RubyRange.java
Original file line number Diff line number Diff line change
@@ -645,64 +645,52 @@ public IRubyObject cover_p(ThreadContext context, IRubyObject obj) {

@JRubyMethod(frame = true)
public IRubyObject min(ThreadContext context, Block block) {
IRubyObject receiver = getReceiverForMinMax(context, end, block);
if(receiver.isNil()) return receiver;
return Helpers.invokeSuper(context, receiver, block);
if (block.isGiven()) return Helpers.invokeSuper(context, this, block);

int cmp = RubyComparable.cmpint(context, invokedynamic(context, begin, MethodNames.OP_CMP, end), begin, end);
if (cmp > 0 || (cmp == 0 && isExclusive)) return context.nil;

return begin;
}

@JRubyMethod(frame = true)
public IRubyObject max(ThreadContext context, Block block) {
IRubyObject rangeEnd;
boolean isNumeric = end instanceof RubyNumeric;

if (block.isGiven() || (isExclusive && !isNumeric)) {
return Helpers.invokeSuper(context, this, block);
}

int cmp = RubyComparable.cmpint(context, invokedynamic(context, begin, MethodNames.OP_CMP, end), begin, end);
if (cmp > 0) return context.nil;
if (isExclusive) {
if (!(end instanceof RubyInteger)) {
throw context.runtime.newTypeError("cannot exclude non Integer end value");
}

if (cmp == 0) return context.nil;

if (!(begin instanceof RubyInteger)) {
throw context.runtime.newTypeError("cannot exclude end value with non Integer begin value");
}
if (end instanceof RubyFixnum) {
rangeEnd = RubyFixnum.newFixnum(context.runtime, ((RubyFixnum)end).getLongValue() - 1);
} else {
rangeEnd = end.callMethod(context, "-", RubyFixnum.one(context.runtime));
return RubyFixnum.newFixnum(context.runtime, ((RubyFixnum)end).getLongValue() - 1);
}
} else {
rangeEnd = end;

return end.callMethod(context, "-", RubyFixnum.one(context.runtime));
}

IRubyObject receiver = getReceiverForMinMax(context, rangeEnd, block);
if(receiver.isNil()) return receiver;
return Helpers.invokeSuper(context, receiver, block);
return end;
}

@JRubyMethod(frame = true)
public IRubyObject min(ThreadContext context, IRubyObject arg, Block block) {
if (block.isGiven()) return Helpers.invokeSuper(context, this, block);

return first(context, arg);
return Helpers.invokeSuper(context, this, arg, block);
}

@JRubyMethod(frame = true)
public IRubyObject max(ThreadContext context, IRubyObject arg, Block block) {
if (block.isGiven()) return Helpers.invokeSuper(context, this, block);

return ((RubyArray) last(context, arg)).reverse();
}

private boolean rangeEmpty_p(ThreadContext context) {
int cmp = RubyComparable.cmpint(context, invokedynamic(context, begin, MethodNames.OP_CMP, end), begin, end);
return cmp > 0 || (cmp == 0 && isExclusive);
}

private IRubyObject getReceiverForMinMax(ThreadContext context, IRubyObject rangeEnd, Block block) {
RubyObject receiver;

if (block.isGiven()) {
receiver = this;
} else {
if(rangeEmpty_p(context)) return context.runtime.getNil();
receiver = RubyArray.newArray(context.runtime, new IRubyObject[]{begin, rangeEnd});
}
return receiver;
return Helpers.invokeSuper(context, this, arg, block);
}

@JRubyMethod
1 change: 0 additions & 1 deletion spec/tags/ruby/core/range/max_tags.txt

This file was deleted.

0 comments on commit d0fe3c0

Please sign in to comment.