Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a90d9a8b3ccd
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3e334e0e3a59
Choose a head ref
  • 7 commits
  • 5 files changed
  • 1 contributor

Commits on Mar 3, 2015

  1. Copy the full SHA
    9a62483 View commit details
  2. Copy the full SHA
    1ca61dc View commit details
  3. Copy the full SHA
    6c45667 View commit details
  4. Copy the full SHA
    f143e88 View commit details
  5. Copy the full SHA
    8809091 View commit details
  6. Copy the full SHA
    73af71f View commit details
  7. Copy the full SHA
    3e334e0 View commit details
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/string/slice_tags.txt
Original file line number Diff line number Diff line change
@@ -2,8 +2,6 @@ fails:String#slice with index, length returns subclass instances
fails:String#slice with Range returns subclass instances
fails:String#slice with Range calls to_int on range arguments
fails:String#slice with Range works with Range subclasses
fails:String#slice with Regexp always taints resulting strings when self or regexp is tainted
fails:String#slice with Regexp returns an untrusted string if the regexp is untrusted
fails:String#slice with Regexp returns subclass instances
fails:String#slice with Regexp, index always taints resulting strings when self or regexp is tainted
fails:String#slice with Regexp, index returns an untrusted string if the regexp is untrusted
Original file line number Diff line number Diff line change
@@ -12,12 +12,15 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.joni.exception.ValueException;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.coerce.ToIntNode;
import org.jruby.truffle.nodes.coerce.ToIntNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyArray;
@@ -29,9 +32,11 @@
@CoreClass(name = "MatchData")
public abstract class MatchDataNodes {

@CoreMethod(names = "[]", required = 1, lowerFixnumParameters = 0)
@CoreMethod(names = "[]", required = 1, lowerFixnumParameters = 0, taintFrom = 0)
public abstract static class GetIndexNode extends CoreMethodNode {

@Child private ToIntNode toIntNode;

public GetIndexNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -87,6 +92,18 @@ public Object getIndex(RubyMatchData matchData, RubyString index) {
}
}

@Specialization(guards = { "!isRubySymbol(arguments[1])", "!isRubyString(arguments[1])" })
public Object getIndex(VirtualFrame frame, RubyMatchData matchData, Object index) {
notDesignedForCompilation();

if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeFactory.create(getContext(), getSourceSection(), null));
}

return getIndex(matchData, toIntNode.executeIntegerFixnum(frame, index));
}

}

@CoreMethod(names = "begin", required = 1, lowerFixnumParameters = 1)
Original file line number Diff line number Diff line change
@@ -223,7 +223,7 @@ public RubyString match(RubyRegexp regexp) {

}

@CoreMethod(names = "match", required = 1)
@CoreMethod(names = "match", required = 1, taintFrom = 0)
public abstract static class MatchNode extends CoreMethodNode {

public MatchNode(RubyContext context, SourceSection sourceSection) {
80 changes: 21 additions & 59 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Original file line number Diff line number Diff line change
@@ -284,8 +284,9 @@ private RubyString formatSlow(RubyString format, Object[] args) {
public abstract static class GetIndexNode extends CoreMethodNode {

@Child private ToIntNode toIntNode;
@Child private MatchDataNodes.GetIndexNode getMatchDataIndexNode;
@Child private CallDispatchHeadNode getMatchDataIndexNode;
@Child private CallDispatchHeadNode includeNode;
@Child private CallDispatchHeadNode matchNode;
@Child private KernelNodes.DupNode dupNode;

private final BranchProfile outOfBounds = BranchProfile.create();
@@ -386,77 +387,33 @@ public Object slice(VirtualFrame frame, RubyString string, Object start, Object
}

@Specialization
public Object slice(RubyString string, RubyRegexp regexp, @SuppressWarnings("unused") UndefinedPlaceholder capture) {
public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, @SuppressWarnings("unused") UndefinedPlaceholder capture) {
notDesignedForCompilation();

final Object matchData = regexp.matchCommon(string, false, false);

if (matchData == getContext().getCoreLibrary().getNilObject()) {
return matchData;
}

return ((RubyMatchData) matchData).getValues()[0];
return slice(frame, string, regexp, 0);
}

@Specialization
public Object slice(RubyString string, RubyRegexp regexp, int capture) {
notDesignedForCompilation();

final Object matchData = regexp.matchCommon(string, false, false);

if (matchData == getContext().getCoreLibrary().getNilObject()) {
return matchData;
}

if (getMatchDataIndexNode == null) {
CompilerDirectives.transferToInterpreter();
getMatchDataIndexNode = insert(MatchDataNodesFactory.GetIndexNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}));
}

return getMatchDataIndexNode.getIndex((RubyMatchData) matchData, capture);
}

@Specialization
public Object slice(RubyString string, RubyRegexp regexp, RubyString capture) {
@Specialization(guards = "!isUndefinedPlaceholder(arguments[2])")
public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, Object capture) {
notDesignedForCompilation();

final Object matchData = regexp.matchCommon(string, false, false);

if (matchData == getContext().getCoreLibrary().getNilObject()) {
return matchData;
}

if (getMatchDataIndexNode == null) {
if (matchNode == null) {
CompilerDirectives.transferToInterpreter();
getMatchDataIndexNode = insert(MatchDataNodesFactory.GetIndexNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}));
matchNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return getMatchDataIndexNode.getIndex((RubyMatchData) matchData, capture);
}

@Specialization(guards = { "!isUndefinedPlaceholder(arguments[2])", "!isRubyString(arguments[2])" })
public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, Object capture) {
notDesignedForCompilation();

final Object matchData = regexp.matchCommon(string, false, false);
final Object matchData = matchNode.call(frame, regexp, "match", null, string);

if (matchData == getContext().getCoreLibrary().getNilObject()) {
return matchData;
}

if (toIntNode == null) {
CompilerDirectives.transferToInterpreter();
toIntNode = insert(ToIntNodeFactory.create(getContext(), getSourceSection(), null));
}

if (getMatchDataIndexNode == null) {
CompilerDirectives.transferToInterpreter();
getMatchDataIndexNode = insert(MatchDataNodesFactory.GetIndexNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}));
getMatchDataIndexNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final int index = toIntNode.executeIntegerFixnum(frame, capture);

return getMatchDataIndexNode.getIndex((RubyMatchData) matchData, index);
return getMatchDataIndexNode.call(frame, matchData, "[]", null, capture);
}

@Specialization
@@ -1299,28 +1256,33 @@ public RubyString ljust(RubyString string, int length, RubyString padding) {

}

@CoreMethod(names = "match", required = 1)
@CoreMethod(names = "match", required = 1, taintFrom = 0)
public abstract static class MatchNode extends CoreMethodNode {

@Child private CallDispatchHeadNode regexpMatchNode;

public MatchNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
regexpMatchNode = DispatchHeadNodeFactory.createMethodCall(context);
}

public MatchNode(MatchNode prev) {
super(prev);
regexpMatchNode = prev.regexpMatchNode;
}

@Specialization
public Object match(RubyString string, RubyString regexpString) {
public Object match(VirtualFrame frame, RubyString string, RubyString regexpString) {
notDesignedForCompilation();

final RubyRegexp regexp = new RubyRegexp(this, getContext().getCoreLibrary().getRegexpClass(), regexpString.getBytes(), Option.DEFAULT);
return regexp.matchCommon(string, false, false);

return regexpMatchNode.call(frame, regexp, "match", null, string);
}

@Specialization
public Object match(RubyString string, RubyRegexp regexp) {
return regexp.matchCommon(string, false, false);
public Object match(VirtualFrame frame, RubyString string, RubyRegexp regexp) {
return regexpMatchNode.call(frame, regexp, "match", null, string);
}
}

Original file line number Diff line number Diff line change
@@ -16,7 +16,12 @@
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.object.BooleanLocation;
import com.oracle.truffle.api.object.Location;
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;
import org.jruby.truffle.runtime.backtrace.Backtrace;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.methods.InternalMethod;

@@ -117,6 +122,21 @@ private static void printMethodASTBacktrace(Node currentNode) {
printASTForBacktrace(currentNode.getRootNode(), activeNodes, 0);
}

public static boolean isFrozen(Object object) {
return ((RubyBasicObject) object).isFrozen();
}

public static boolean isTainted(Object o) {
final RubyBasicObject object = (RubyBasicObject) o;

final Shape layout = object.getDynamicObject().getShape();
final Property property = layout.getProperty(RubyBasicObject.TAINTED_IDENTIFIER);

final Location storageLocation = property.getLocation();

return (boolean) storageLocation.get(object.getDynamicObject(), layout);
}

private static void printASTForBacktrace(Node node, List<Node> activeNodes, int indentation) {
for (int n = 0; n < indentation; n++) {
System.err.print(" ");