Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use MethodParameter attribute if code attribute is missing #19

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.benf.cfr.reader.bytecode.analysis.variables;

import org.benf.cfr.reader.bytecode.analysis.types.MethodPrototype;
import org.benf.cfr.reader.entities.attributes.MethodParameterEntry;
import org.benf.cfr.reader.util.output.Dumper;

import java.util.List;

public class NamedVariableMethodParameter implements NamedVariable {
private String name;
private boolean forced = false;
private List<MethodParameterEntry> parameters;

public NamedVariableMethodParameter(List<MethodParameterEntry> parameters, String name) {
this.name = name;
this.parameters = parameters;
}

@Override
public void forceName(String name) {
this.name = name;
forced = true;
}

@Override
public String getStringName() {
return this.name;
}

@Override
public boolean isGoodName() {
return true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, no good if it's 0-name; it's totally legal to have null name in MethodParameters (storing parameter flags only) but valid name in LocalVariableTable/LocalVariableTypeTable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what exactly isGoodName is supposed to represent, but I don't see a very easy way to fix this currently since this doesn't know which parameter it is until dumpParameter is called...

}

@Override
public Dumper dump(Dumper d) {
return dump(d, false);
}

@Override
public Dumper dump(Dumper d, boolean defines) {
return d.variableName(name, this, defines);
}

@Override
public Dumper dumpParameter(Dumper d, MethodPrototype prototype, int index, boolean defines) {
return d.parameterName(forced ? name : parameters.get(index).name.getValue(), this, prototype, index, defines);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, will NPE on .getValue

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.benf.cfr.reader.bytecode.analysis.variables;

import org.benf.cfr.reader.entities.attributes.LocalVariableEntry;
import org.benf.cfr.reader.entities.attributes.MethodParameterEntry;
import org.benf.cfr.reader.util.collections.MapFactory;

import java.util.List;
import java.util.Map;

public class VariableNamerMethodParameter implements VariableNamer {
private final VariableNamer missingNamer = new VariableNamerDefault();
private final List<MethodParameterEntry> parameters;
private final Map<LocalVariableEntry, NamedVariable> cache = MapFactory.newMap();

public VariableNamerMethodParameter(List<MethodParameterEntry> parameters) {
this.parameters = parameters;
}

@Override
public NamedVariable getName(int originalRawOffset, Ident ident, long stackPosition, boolean clashed) {
return new NamedVariableMethodParameter(parameters, null);
}

@Override
public List<NamedVariable> getNamedVariables() {
return missingNamer.getNamedVariables();
}

@Override
public void mutatingRenameUnClash(NamedVariable toRename) {
missingNamer.mutatingRenameUnClash(toRename);
}

@Override
public void forceName(Ident ident, long stackPosition, String name) {
missingNamer.forceName(ident, stackPosition, name);
}
}
8 changes: 7 additions & 1 deletion src/org/benf/cfr/reader/entities/Method.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.benf.cfr.reader.bytecode.analysis.variables.VariableNamerFactory;
import org.benf.cfr.reader.bytecode.analysis.types.*;
import org.benf.cfr.reader.bytecode.analysis.types.DeclarationAnnotationHelper.DeclarationAnnotationsInfo;
import org.benf.cfr.reader.bytecode.analysis.variables.VariableNamerMethodParameter;
import org.benf.cfr.reader.entities.annotations.AnnotationTableEntry;
import org.benf.cfr.reader.entities.annotations.AnnotationTableTypeEntry;
import org.benf.cfr.reader.entities.annotations.ElementValue;
Expand Down Expand Up @@ -145,7 +146,12 @@ public Method(ByteData raw, ClassFile classFile, final ConstantPool cp, final DC
AttributeCode codeAttribute = attributes.getByName(AttributeCode.ATTRIBUTE_NAME);
if (codeAttribute == null) {
// Because we don't have a code attribute, we don't have a local variable table.
this.variableNamer = VariableNamerFactory.getNamer(null, cp);
AttributeMethodParameters methodParameters = attributes.getByName(AttributeMethodParameters.ATTRIBUTE_NAME);
if (methodParameters != null) {
this.variableNamer = new VariableNamerMethodParameter(methodParameters.getParameters());
} else {
this.variableNamer = VariableNamerFactory.getNamer(null, cp);
}
this.codeAttribute = null;
} else {
this.codeAttribute = codeAttribute;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.benf.cfr.reader.entities.attributes;

import org.benf.cfr.reader.entities.constantpool.ConstantPool;
import org.benf.cfr.reader.util.bytestream.ByteData;
import org.benf.cfr.reader.util.collections.ListFactory;
import org.benf.cfr.reader.util.output.Dumper;

import java.util.List;

public class AttributeMethodParameters extends Attribute {
public static final String ATTRIBUTE_NAME = "MethodParameters";

private static final long OFFSET_OF_ATTRIBUTE_LENGTH = 2;
private static final long OFFSET_OF_REMAINDER = 6;
private static final long OFFSET_OF_PARAMETERS_COUNT = 6;
private static final long OFFSET_OF_PARAMETERS = 7;

private final int length;
private final int count;
private final List<MethodParameterEntry> parameters = ListFactory.newList();

public AttributeMethodParameters(ByteData raw, ConstantPool cp) {
this.length = raw.getS4At(OFFSET_OF_ATTRIBUTE_LENGTH);
this.count = raw.getU1At(OFFSET_OF_PARAMETERS_COUNT);
long offset = OFFSET_OF_PARAMETERS;
for (long i = 0; i < count; i++) {
int nameIndex = raw.getU2At(offset);
int accessFlags = raw.getU2At(offset + 2);
parameters.add(new MethodParameterEntry(cp.getEntry(nameIndex), accessFlags));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nameIndex may be 0, indicating null. getEntry does not accept 0 arguments:

if (index == 0) throw new ConfusedCFRException("Attempt to fetch element 0 from constant pool");

}
}

public int getParameterCount() {
return count;
}

public List<MethodParameterEntry> getParameters() {
return parameters;
}

@Override
public Dumper dump(Dumper d) {
return d.print(ATTRIBUTE_NAME);
}

@Override
public String getRawName() {
return ATTRIBUTE_NAME;
}

@Override
public long getRawByteLength() {
return OFFSET_OF_REMAINDER + length;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.benf.cfr.reader.entities.attributes;

import org.benf.cfr.reader.entities.constantpool.ConstantPoolEntry;
import org.benf.cfr.reader.entities.constantpool.ConstantPoolEntryUTF8;

public class MethodParameterEntry {
public final ConstantPoolEntryUTF8 name;
public final int accessFlags;

public MethodParameterEntry(ConstantPoolEntry name, int accessFlags) {
this.name = (ConstantPoolEntryUTF8) name;
this.accessFlags = accessFlags;
}
}
2 changes: 2 additions & 0 deletions src/org/benf/cfr/reader/entityfactories/AttributeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public static Attribute build(ByteData raw, ConstantPool cp, ClassFileVersion cl
return new AttributeRecord(raw, cp, classFileVersion);
} else if (AttributePermittedSubclasses.ATTRIBUTE_NAME.equals(attributeName)) {
return new AttributePermittedSubclasses(raw, cp);
} else if (AttributeMethodParameters.ATTRIBUTE_NAME.equals(attributeName)) {
return new AttributeMethodParameters(raw, cp);
}
} catch (Exception e) {
// Can't handle it? Continue and process as an unknown attribute.
Expand Down