Commit dc02c81f authored by Lukáš Marek's avatar Lukáš Marek
Browse files

Additional checking for processor methods

parent 5ee766a0
......@@ -3,10 +3,15 @@ package ch.usi.dag.disl.classparser;
import java.lang.reflect.Field;
import java.util.Iterator;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.VarInsnNode;
import ch.usi.dag.disl.exception.DiSLFatalException;
import ch.usi.dag.disl.exception.ParserException;
import ch.usi.dag.disl.exception.ReflectionException;
import ch.usi.dag.disl.util.ReflectionHelper;
......@@ -62,4 +67,54 @@ abstract class ParserHelper {
"Reflection error wihle parsing annotation", e);
}
}
public static void usesContextProperly(String className, String methodName,
String methodDescriptor, InsnList instructions)
throws ParserException {
Type[] types = Type.getArgumentTypes(methodDescriptor);
int maxArgIndex = 0;
// count the max index of arguments
for (int i = 0; i < types.length; i++) {
// add number of occupied slots
maxArgIndex += types[i].getSize();
}
// The following code assumes that all disl snippets are static
for (AbstractInsnNode instr : instructions.toArray()) {
switch (instr.getOpcode()) {
// test if the context is stored somewhere else
case Opcodes.ALOAD: {
int local = ((VarInsnNode) instr).var;
if (local < maxArgIndex
&& instr.getNext().getOpcode() == Opcodes.ASTORE) {
throw new ParserException("In method " + className
+ "." + methodName + " - method parameter"
+ " (context) cannot be stored into local"
+ " variable");
}
break;
}
// test if something is stored in the context
case Opcodes.ASTORE: {
int local = ((VarInsnNode) instr).var;
if (local < maxArgIndex) {
throw new ParserException("In method " + className
+ "." + methodName + " - method parameter"
+ " (context) cannot be overwritten");
}
break;
}
}
}
}
}
......@@ -86,7 +86,7 @@ class ProcessorParser extends AbstractParser {
private ProcMethod parseProcessorMethod(String className, MethodNode method)
throws ProcessorParserException, ReflectionException,
StaticContextGenException, GuardException {
StaticContextGenException, GuardException, ParserException {
String fullMethodName = className + "." + method.name;
......@@ -138,6 +138,19 @@ class ProcessorParser extends AbstractParser {
Method guardMethod = GuardHelper.findAndValidateGuardMethod(guardClass,
GuardHelper.processorContextSet());
// ** checks **
// detect empty snippets
if (AsmHelper.containsOnlyReturn(method.instructions)) {
throw new ProcessorParserException("Method " + className + "."
+ method.name + " cannot be empty");
}
// context arguments (local variables 1, 2, ...) cannot be stored or
// overwritten, may be used only in method calls
ParserHelper.usesContextProperly(className, method.name, method.desc,
method.instructions);
// ** create unprocessed code holder class **
// code is processed after everything is parsed
ProcUnprocessedCode ucd = new ProcUnprocessedCode(method.instructions,
......
......@@ -8,12 +8,9 @@ import java.util.Set;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import ch.usi.dag.disl.annotation.After;
import ch.usi.dag.disl.annotation.AfterReturning;
......@@ -83,7 +80,7 @@ class SnippetParser extends AbstractParser {
private Snippet parseSnippet(String className, MethodNode method)
throws SnippetParserException, ReflectionException,
ScopeParserException, StaticContextGenException, MarkerException,
GuardException {
GuardException, ParserException {
// check annotation
if (method.invisibleAnnotations == null) {
......@@ -145,7 +142,7 @@ class SnippetParser extends AbstractParser {
// context arguments (local variables 1, 2, ...) cannot be stored or
// overwritten, may be used only in method calls
usesContextProperly(className, method.name, method.desc,
ParserHelper.usesContextProperly(className, method.name, method.desc,
method.instructions);
// ** create unprocessed code holder class **
......@@ -329,54 +326,4 @@ class SnippetParser extends AbstractParser {
return new Contexts(knownStCo, usesDynamicContext, usesProcessorContext);
}
private void usesContextProperly(String className, String methodName,
String methodDescriptor, InsnList instructions)
throws SnippetParserException {
Type[] types = Type.getArgumentTypes(methodDescriptor);
int maxArgIndex = 0;
// count the max index of arguments
for (int i = 0; i < types.length; i++) {
// add number of occupied slots
maxArgIndex += types[i].getSize();
}
// The following code assumes that all disl snippets are static
for (AbstractInsnNode instr : instructions.toArray()) {
switch (instr.getOpcode()) {
// test if the context is stored somewhere else
case Opcodes.ALOAD: {
int local = ((VarInsnNode) instr).var;
if (local < maxArgIndex
&& instr.getNext().getOpcode() == Opcodes.ASTORE) {
throw new SnippetParserException("In snippet " + className
+ "." + methodName + " - snippet parameter"
+ " (context) cannot be stored into local"
+ " variable");
}
break;
}
// test if something is stored in the context
case Opcodes.ASTORE: {
int local = ((VarInsnNode) instr).var;
if (local < maxArgIndex) {
throw new SnippetParserException("In snippet " + className
+ "." + methodName + " - snippet parameter"
+ " (context) cannot overwritten");
}
break;
}
}
}
}
}
......@@ -8,7 +8,7 @@ public interface StaticContext {
// NOTE: all static context methods should follow convention:
// a) static context methods does not have parameters
// b) return value can be only basic type (+String)
// b) return value can be only basic type or String
public void staticContextData(Shadow sa);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment