Skip to content

Commit

Permalink
fix: Missing 'allow-0-case' for inner class's name index
Browse files Browse the repository at this point in the history
Also start on type annotation target-info validation
  • Loading branch information
Col-E committed Feb 18, 2022
1 parent 7b78a82 commit 799a4f3
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package me.coley.cafedude.classfile.annotation;

import me.coley.cafedude.classfile.attribute.ExceptionsAttribute;
import me.coley.cafedude.classfile.attribute.LocalVariableTableAttribute;
import me.coley.cafedude.classfile.behavior.CpAccessor;

import java.util.Collections;
Expand Down Expand Up @@ -86,6 +88,7 @@ public int computeLength() {
* of a class or interface declaration.
*/
public static class SuperTypeTargetInfo extends TargetInfo {
public static final int EXTENDS = 65535;
private final int superTypeIndex;

/**
Expand All @@ -101,6 +104,13 @@ public SuperTypeTargetInfo(int targetType, int superTypeIndex) {
this.superTypeIndex = superTypeIndex;
}

/**
* @return {@code} true when {@link #getSuperTypeIndex()} is 65535.
*/
public boolean isExtends() {
return superTypeIndex == EXTENDS;
}

/**
* @return For {@code extends} index is 65535.
* Otherwise the index indicates the interface index of the associated class.
Expand Down Expand Up @@ -231,9 +241,8 @@ public static class ThrowsTargetInfo extends TargetInfo {
* indicating the purpose of the {@code target_info}.
* @param throwsTypeIndex
* Index of the thrown type in the associated {@code exception_index_table}
* of the {@code Exceptions} attribute.
* of the {@link ExceptionsAttribute}.
*/
// TODO: When done parsing Exceptions update javadocs to link to the type here
public ThrowsTargetInfo(int targetType, int throwsTypeIndex) {
super(TargetInfoType.THROWS_TARGET, targetType);
this.throwsTypeIndex = throwsTypeIndex;
Expand All @@ -258,9 +267,8 @@ public int computeLength() {
* Indicates that an annotation appears on the type of a local variable.
* <br>
* Marked variables types are annotated but are not listed directly.
* The information provided should be matched with what appears in the local variable attribute.
* The information provided should be matched with what appears in the {@link LocalVariableTableAttribute}.
*/
// TODO: When LocalVariableAttribute is creates update the javadoc to link to it
public static class LocalVarTargetInfo extends TargetInfo {
private final List<Variable> variableTable;

Expand Down
13 changes: 9 additions & 4 deletions src/main/java/me/coley/cafedude/io/AttributeReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,16 @@ public Attribute readAttribute(AttributeContext context) throws IOException {
return null;
}
return attribute;
} catch (IOException ex) {
} catch (Exception ex) {
if (reader.doDropEofAttributes()) {
String name = ((CpUtf8) builder.getPool().get(nameIndex)).getText();
logger.debug("Invalid '{}' on {}, EOF thrown when parsing attribute, expected {} bytes",
name, context.name(), expectedContentLength);
if (nameIndex < builder.getPool().size()) {
String name = ((CpUtf8) builder.getPool().get(nameIndex)).getText();
logger.debug("Invalid '{}' on {}, EOF thrown when parsing attribute, expected {} bytes",
name, context.name(), expectedContentLength);
} else {
logger.debug("Invalid attribute on {}, invalid attribute name index", context.name());
}

return null;
} else
throw ex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
import me.coley.cafedude.classfile.annotation.ElementValue;
import me.coley.cafedude.classfile.annotation.EnumElementValue;
import me.coley.cafedude.classfile.annotation.PrimitiveElementValue;
import me.coley.cafedude.classfile.annotation.TargetInfo;
import me.coley.cafedude.classfile.annotation.TargetInfo.CatchTargetInfo;
import me.coley.cafedude.classfile.annotation.TargetInfo.SuperTypeTargetInfo;
import me.coley.cafedude.classfile.annotation.TypeAnnotation;
import me.coley.cafedude.classfile.annotation.Utf8ElementValue;
import me.coley.cafedude.classfile.attribute.AnnotationDefaultAttribute;
import me.coley.cafedude.classfile.attribute.AnnotationsAttribute;
Expand Down Expand Up @@ -68,6 +72,7 @@
* @author Matt Coley
*/
public class IllegalStrippingTransformer extends Transformer {
private static final int FORCE_FAIL = -1;
private static final Logger logger = LoggerFactory.getLogger(IllegalStrippingTransformer.class);

/**
Expand Down Expand Up @@ -217,7 +222,9 @@ private boolean isValid(AttributeHolder holder, Attribute attribute) {
expectedTypeMasks.put(innerClass.getOuterClassInfoIndex(), i -> i == 0 || i == ConstantPool.CLASS);
// 0 if anonymous, otherwise name index
expectedTypeMasks.put(innerClass.getInnerNameIndex(), i -> i == 0 || i == ConstantPool.UTF8);
allow0Case |= innerClass.getInnerClassInfoIndex() == 0 || innerClass.getOuterClassInfoIndex() == 0;
allow0Case |= innerClass.getInnerClassInfoIndex() == 0
|| innerClass.getOuterClassInfoIndex() == 0
|| innerClass.getInnerNameIndex() == 0;
}
break;
case CODE: {
Expand Down Expand Up @@ -395,7 +402,62 @@ private void addAnnotationValidation(AttributeHolder holder,
cpEntryValidators.put(elementTypeIndex, matchUtf8ClassType());
addElementValueValidation(holder, expectedTypeMasks, cpEntryValidators, entry.getValue());
}
// TODO: Intra-reference checks
if (anno instanceof TypeAnnotation) {
TypeAnnotation typeAnnotation = (TypeAnnotation) anno;
TargetInfo targetInfo = typeAnnotation.getTargetInfo();
switch (targetInfo.getTargetTypeKind()) {
case TYPE_PARAMETER_BOUND_TARGET:
break;
case TYPE_PARAMETER_TARGET:
break;
case FORMAL_PARAMETER_TARGET:
break;
case TYPE_ARGUMENT_TARGET:
break;
case LOCALVAR_TARGET:
// TODO: Ensure variables outline matches what is in code's variables attribute
break;
case THROWS_TARGET:
// TODO: Verify with a sample what the target holder type should be
break;
case OFFSET_TARGET:
// TODO: relies on instructions being parsed
break;
case SUPERTYPE_TARGET:
if (holder instanceof ClassFile) {
SuperTypeTargetInfo superTypeTargetInfo = (SuperTypeTargetInfo) targetInfo;
if (!superTypeTargetInfo.isExtends()) {
ClassFile classFile = (ClassFile) holder;
// Enforce interfaces range
if (superTypeTargetInfo.getSuperTypeIndex() >= classFile.getInterfaceIndices().size()) {
expectedTypeMasks.put(FORCE_FAIL, i -> false);
}
}
} else {
// Illegal target kind for situation
expectedTypeMasks.put(FORCE_FAIL, i -> false);
}
break;

case CATCH_TARGET:
if (holder instanceof CodeAttribute) {
CodeAttribute code = (CodeAttribute) holder;
CatchTargetInfo catchTargetInfo = (CatchTargetInfo) targetInfo;
// Enforce table range
if (catchTargetInfo.getExceptionTableIndex() >= code.getExceptionTable().size()) {
expectedTypeMasks.put(FORCE_FAIL, i -> false);
}
} else {
// Illegal target kind for situation
expectedTypeMasks.put(FORCE_FAIL, i -> false);
}
break;
case EMPTY_TARGET:
default:
// no-op
break;
}
}
}

private void addElementValueValidation(AttributeHolder holder,
Expand Down
Binary file added src/test/resources/samples/crasher/sample28.class
Binary file not shown.
Binary file added src/test/resources/samples/crasher/sample29.class
Binary file not shown.

0 comments on commit 799a4f3

Please sign in to comment.