io.github.dmlloyd.classfile.impl.verifier.VerificationWrapper Maven / Gradle / Ivy
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package io.github.dmlloyd.classfile.impl.verifier;
import java.lang.constant.ClassDesc;
import java.util.LinkedList;
import java.util.List;
import io.github.dmlloyd.classfile.constantpool.ClassEntry;
import io.github.dmlloyd.classfile.constantpool.DynamicConstantPoolEntry;
import io.github.dmlloyd.classfile.constantpool.MemberRefEntry;
import io.github.dmlloyd.classfile.constantpool.NameAndTypeEntry;
import io.github.dmlloyd.classfile.extras.reflect.AccessFlag;
import java.util.stream.Collectors;
import io.github.dmlloyd.classfile.ClassModel;
import io.github.dmlloyd.classfile.constantpool.ConstantPool;
import io.github.dmlloyd.classfile.MethodModel;
import io.github.dmlloyd.classfile.attribute.LocalVariableInfo;
import io.github.dmlloyd.classfile.Attributes;
import io.github.dmlloyd.classfile.impl.BoundAttribute;
import io.github.dmlloyd.classfile.impl.CodeImpl;
import io.github.dmlloyd.classfile.impl.Util;
public final class VerificationWrapper {
private final ClassModel clm;
private final ConstantPoolWrapper cp;
public VerificationWrapper(ClassModel clm) {
this.clm = clm;
this.cp = new ConstantPoolWrapper(clm.constantPool());
}
String thisClassName() {
return clm.thisClass().asInternalName();
}
int majorVersion() {
return clm.majorVersion();
}
String superclassName() {
return clm.superclass().map(ClassEntry::asInternalName).orElse(null);
}
Iterable interfaceNames() {
return Util.mappedList(clm.interfaces(), ClassEntry::asInternalName);
}
Iterable methods() {
return clm.methods().stream().map(m -> new MethodWrapper(m)).toList();
}
boolean findField(String name, String sig) {
for (var f : clm.fields())
if (f.fieldName().stringValue().equals(name) && f.fieldType().stringValue().equals(sig))
return true;
return false;
}
class MethodWrapper {
final MethodModel m;
private final CodeImpl c;
private final List exc;
MethodWrapper(MethodModel m) {
this.m = m;
this.c = (CodeImpl)m.code().orElse(null);
exc = new LinkedList<>();
if (c != null) c.iterateExceptionHandlers((start, end, handler, catchType) -> {
exc.add(new int[] {start, end, handler, catchType});
});
}
ConstantPoolWrapper constantPool() {
return cp;
}
boolean isNative() {
return m.flags().has(AccessFlag.NATIVE);
}
boolean isAbstract() {
return m.flags().has(AccessFlag.ABSTRACT);
}
boolean isBridge() {
return m.flags().has(AccessFlag.BRIDGE);
}
boolean isStatic() {
return m.flags().has(AccessFlag.STATIC);
}
String name() {
return m.methodName().stringValue();
}
int maxStack() {
return c == null ? 0 : c.maxStack();
}
int maxLocals() {
return c == null ? 0 : c.maxLocals();
}
String descriptor() {
return m.methodType().stringValue();
}
String parameters() {
return m.methodTypeSymbol().parameterList().stream().map(ClassDesc::displayName).collect(Collectors.joining(","));
}
int codeLength() {
return c == null ? 0 : c.codeLength();
}
byte[] codeArray() {
return c == null ? null : c.codeArray();
}
List exceptionTable() {
return exc;
}
List localVariableTable() {
var attro = c.findAttribute(Attributes.localVariableTable());
return attro.map(lvta -> lvta.localVariables()).orElse(List.of());
}
byte[] stackMapTableRawData() {
var attro = c.findAttribute(Attributes.stackMapTable());
return attro.map(attr -> ((BoundAttribute) attr).contents()).orElse(null);
}
}
static class ConstantPoolWrapper {
private final ConstantPool cp;
ConstantPoolWrapper(ConstantPool cp) {
this.cp = cp;
}
int entryCount() {
return cp.size();
}
String classNameAt(int index) {
return cp.entryByIndex(index, ClassEntry.class).asInternalName();
}
String dynamicConstantSignatureAt(int index) {
return cp.entryByIndex(index, DynamicConstantPoolEntry.class).type().stringValue();
}
int tagAt(int index) {
return cp.entryByIndex(index).tag();
}
private NameAndTypeEntry _refNameType(int index) {
var e = cp.entryByIndex(index);
return (e instanceof DynamicConstantPoolEntry de) ? de.nameAndType() :
e != null ? ((MemberRefEntry)e).nameAndType() : null;
}
String refNameAt(int index) {
return _refNameType(index).name().stringValue();
}
String refSignatureAt(int index) {
return _refNameType(index).type().stringValue();
}
int refClassIndexAt(int index) {
return cp.entryByIndex(index, MemberRefEntry.class).owner().index();
}
}
}