From dd14c75325e7c5a442f846036dc6d77682aba30b Mon Sep 17 00:00:00 2001 From: qwertyuioplkjhgfd Date: Tue, 2 May 2023 20:24:36 -0700 Subject: [PATCH 1/2] use MethodParameter attributes if code attribute is missing --- .../NamedVariableMethodParameter.java | 49 +++++++++++++++++ .../VariableNamerMethodParameter.java | 38 +++++++++++++ src/org/benf/cfr/reader/entities/Method.java | 8 ++- .../attributes/AttributeMethodParameters.java | 55 +++++++++++++++++++ .../attributes/MethodParameterEntry.java | 14 +++++ .../entityfactories/AttributeFactory.java | 2 + 6 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java create mode 100644 src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java create mode 100644 src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java create mode 100644 src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java diff --git a/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java b/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java new file mode 100644 index 00000000..5dc4c97c --- /dev/null +++ b/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java @@ -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 parameters; + + public NamedVariableMethodParameter(List 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; + } + + @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); + } +} diff --git a/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java b/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java new file mode 100644 index 00000000..f25354cf --- /dev/null +++ b/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java @@ -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 parameters; + private final Map cache = MapFactory.newMap(); + + public VariableNamerMethodParameter(List parameters) { + this.parameters = parameters; + } + + @Override + public NamedVariable getName(int originalRawOffset, Ident ident, long stackPosition, boolean clashed) { + return new NamedVariableMethodParameter(parameters, null); + } + + @Override + public List 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); + } +} diff --git a/src/org/benf/cfr/reader/entities/Method.java b/src/org/benf/cfr/reader/entities/Method.java index ace693ab..7fffd530 100644 --- a/src/org/benf/cfr/reader/entities/Method.java +++ b/src/org/benf/cfr/reader/entities/Method.java @@ -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; @@ -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; diff --git a/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java b/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java new file mode 100644 index 00000000..eaf006a2 --- /dev/null +++ b/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java @@ -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 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)); + } + } + + public int getParameterCount() { + return count; + } + + public List 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; + } +} diff --git a/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java b/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java new file mode 100644 index 00000000..4de263a5 --- /dev/null +++ b/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java @@ -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; + } +} diff --git a/src/org/benf/cfr/reader/entityfactories/AttributeFactory.java b/src/org/benf/cfr/reader/entityfactories/AttributeFactory.java index 9deab0e5..cc46f357 100644 --- a/src/org/benf/cfr/reader/entityfactories/AttributeFactory.java +++ b/src/org/benf/cfr/reader/entityfactories/AttributeFactory.java @@ -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. From 5bf157d896e7c87404798e8ace5f47dda93ac058 Mon Sep 17 00:00:00 2001 From: qwertyuioplkjhgfd Date: Wed, 3 May 2023 09:17:09 -0700 Subject: [PATCH 2/2] check for 0 nameIndex --- .../variables/NamedVariableMethodParameter.java | 17 ++++++++++++++--- .../variables/VariableNamerMethodParameter.java | 8 +++++--- src/org/benf/cfr/reader/entities/Method.java | 2 +- .../attributes/AttributeMethodParameters.java | 2 +- .../attributes/MethodParameterEntry.java | 7 +++---- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java b/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java index 5dc4c97c..ab7b9d34 100644 --- a/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java +++ b/src/org/benf/cfr/reader/bytecode/analysis/variables/NamedVariableMethodParameter.java @@ -2,6 +2,8 @@ import org.benf.cfr.reader.bytecode.analysis.types.MethodPrototype; import org.benf.cfr.reader.entities.attributes.MethodParameterEntry; +import org.benf.cfr.reader.entities.constantpool.ConstantPool; +import org.benf.cfr.reader.entities.constantpool.ConstantPoolEntryUTF8; import org.benf.cfr.reader.util.output.Dumper; import java.util.List; @@ -9,11 +11,13 @@ public class NamedVariableMethodParameter implements NamedVariable { private String name; private boolean forced = false; - private List parameters; + private final List parameters; + private final ConstantPool cp; - public NamedVariableMethodParameter(List parameters, String name) { + public NamedVariableMethodParameter(List parameters, String name, ConstantPool cp) { this.name = name; this.parameters = parameters; + this.cp = cp; } @Override @@ -44,6 +48,13 @@ public Dumper dump(Dumper d, boolean 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); + if (forced) { + return d.parameterName(name, this, prototype, index, defines); + } + int nameIndex = parameters.get(index).nameIndex; + if (nameIndex == 0) { + return d.parameterName(name, this, prototype, index, defines); + } + return d.parameterName(((ConstantPoolEntryUTF8)cp.getEntry(nameIndex)).getValue(), this, prototype, index, defines); } } diff --git a/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java b/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java index f25354cf..36bf6c64 100644 --- a/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java +++ b/src/org/benf/cfr/reader/bytecode/analysis/variables/VariableNamerMethodParameter.java @@ -2,6 +2,7 @@ import org.benf.cfr.reader.entities.attributes.LocalVariableEntry; import org.benf.cfr.reader.entities.attributes.MethodParameterEntry; +import org.benf.cfr.reader.entities.constantpool.ConstantPool; import org.benf.cfr.reader.util.collections.MapFactory; import java.util.List; @@ -10,15 +11,16 @@ public class VariableNamerMethodParameter implements VariableNamer { private final VariableNamer missingNamer = new VariableNamerDefault(); private final List parameters; - private final Map cache = MapFactory.newMap(); + private final ConstantPool cp; - public VariableNamerMethodParameter(List parameters) { + public VariableNamerMethodParameter(List parameters, ConstantPool cp) { this.parameters = parameters; + this.cp = cp; } @Override public NamedVariable getName(int originalRawOffset, Ident ident, long stackPosition, boolean clashed) { - return new NamedVariableMethodParameter(parameters, null); + return new NamedVariableMethodParameter(parameters, null, cp); } @Override diff --git a/src/org/benf/cfr/reader/entities/Method.java b/src/org/benf/cfr/reader/entities/Method.java index 7fffd530..b3f1078d 100644 --- a/src/org/benf/cfr/reader/entities/Method.java +++ b/src/org/benf/cfr/reader/entities/Method.java @@ -148,7 +148,7 @@ public Method(ByteData raw, ClassFile classFile, final ConstantPool cp, final DC // Because we don't have a code attribute, we don't have a local variable table. AttributeMethodParameters methodParameters = attributes.getByName(AttributeMethodParameters.ATTRIBUTE_NAME); if (methodParameters != null) { - this.variableNamer = new VariableNamerMethodParameter(methodParameters.getParameters()); + this.variableNamer = new VariableNamerMethodParameter(methodParameters.getParameters(), cp); } else { this.variableNamer = VariableNamerFactory.getNamer(null, cp); } diff --git a/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java b/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java index eaf006a2..4417eb10 100644 --- a/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java +++ b/src/org/benf/cfr/reader/entities/attributes/AttributeMethodParameters.java @@ -26,7 +26,7 @@ public AttributeMethodParameters(ByteData raw, ConstantPool cp) { 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)); + parameters.add(new MethodParameterEntry(nameIndex, accessFlags)); } } diff --git a/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java b/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java index 4de263a5..7fe556de 100644 --- a/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java +++ b/src/org/benf/cfr/reader/entities/attributes/MethodParameterEntry.java @@ -1,14 +1,13 @@ 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 nameIndex; public final int accessFlags; - public MethodParameterEntry(ConstantPoolEntry name, int accessFlags) { - this.name = (ConstantPoolEntryUTF8) name; + public MethodParameterEntry(int nameIndex, int accessFlags) { + this.nameIndex = nameIndex; this.accessFlags = accessFlags; } }