下面列出了org.objectweb.asm.Handle#getTag ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkMethodIdentifier(version, name, "name");
checkMethodDescriptor(version, descriptor);
if (bootstrapMethodHandle.getTag() != Opcodes.H_INVOKESTATIC
&& bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
throw new IllegalArgumentException("invalid handle tag " + bootstrapMethodHandle.getTag());
}
for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
checkLdcConstant(bootstrapMethodArgument);
}
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
++insnCount;
}
protected void _dynamic_call(Handle bsm, Object[] bsmArgs, String bootstrapDesc, String boundName) {
save_stack(false);
// these are the additional bound variables passed into the boostrap method (typically metafactory)
Expr[] boundArgs = new Expr[Type.getArgumentTypes(bootstrapDesc).length];
for(int i = boundArgs.length - 1; i >= 0; i--) {
boundArgs[i] = pop();
}
// copy the bsm and bsm args
Handle bsmCopy = new Handle(bsm.getTag(), bsm.getOwner(), bsm.getName(), bsm.getDesc());
Handle provider = new Handle(bsm.getTag(), bsm.getOwner(), bsm.getName(), bsm.getDesc());
Object[] bsmArgsCopy = new Object[bsmArgs.length];
System.arraycopy(bsmArgs, 0, bsmArgsCopy, 0, bsmArgsCopy.length);
DynamicInvocationExpr expr = new DynamicInvocationExpr(bsmCopy, bsmArgsCopy, bootstrapDesc, boundArgs, boundName);
if(expr.getType() == Type.VOID_TYPE) {
addStmt(new PopStmt(expr));
} else {
int index = currentStack.height();
Type type = assign_stack(index, expr);
push(load_stack(index, type));
}
// TODO: redo vm lambdas as static resolution calls/concrete calls.
}
@Override
public Set<MethodNode> resolveTargets(InvocationResolver res) {
// this is probably like 99% of all the invokedynamics
if (bootstrapMethod.getOwner().equals("java/lang/invoke/LambdaMetafactory")
&& bootstrapMethod.getName().equals("metafactory")) {
assert (bootstrapArgs.length == 3 && bootstrapArgs[1] instanceof Handle);
Handle boundFunc = (Handle) bootstrapArgs[1];
switch (boundFunc.getTag()) {
case Opcodes.H_INVOKESTATIC:
return StaticInvocationExpr.resolveStaticCall(res, boundFunc.getOwner(), boundFunc.getName(), boundFunc.getDesc());
case Opcodes.H_INVOKESPECIAL:
assert(boundFunc.getName().equals("<init>"));
return VirtualInvocationExpr.resolveSpecialInvocation(res, boundFunc.getOwner(), boundFunc.getDesc());
case Opcodes.H_INVOKEINTERFACE:
case Opcodes.H_INVOKEVIRTUAL:
return VirtualInvocationExpr.resolveVirtualInvocation(res, boundFunc.getOwner(), boundFunc.getOwner(), boundFunc.getDesc());
default:
throw new IllegalArgumentException("Unexpected metafactory bootstrap tag?? " + boundFunc.getTag());
}
}
return new HashSet<>();
}
@Override
public void visitInvokeDynamicInsn(String origMethodName, String methodDescriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
String methodOwner = bootstrapMethodHandle.getOwner();
if (isStringConcatIndy(methodOwner, origMethodName)) {
handleStringConcatIndy(origMethodName, methodDescriptor, bootstrapMethodHandle, bootstrapMethodArguments);
} else if (isLambdaIndy(methodOwner)) {
// AKI-130: The bootstrap methodDescriptor to this metafactory must NOT require additional arguments (since that would require dynamic class generation for each callsite - potential attack vector).
if (!methodDescriptor.startsWith("()")) {
throw RejectedClassException.invokeDynamicBootstrapMethodArguments(methodDescriptor);
}
// This is really just a specialization of the above call to check the return type (this would need to be changed if we accepted arguments).
if (!RUNNABLE_DESCRIPTOR.equals(methodDescriptor) && !FUNCTION_DESCRIPTOR.equals(methodDescriptor)) {
throw RejectedClassException.invokeDynamicLambdaType(methodDescriptor);
}
if (bootstrapMethodHandle.getTag() != Opcodes.H_INVOKEVIRTUAL && bootstrapMethodHandle.getTag() != Opcodes.H_INVOKESTATIC
&& bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL && bootstrapMethodHandle.getTag() != Opcodes.H_INVOKEINTERFACE) {
throw RejectedClassException.invokeDynamicHandleType(bootstrapMethodHandle.getTag(), methodDescriptor);
}
handleLambdaIndy(origMethodName, methodDescriptor, bootstrapMethodHandle, bootstrapMethodArguments);
} else {
throw RejectedClassException.invokeDynamicUnsupportedMethodOwner(origMethodName, methodOwner);
}
}
private void registerMethodHandleType(Handle handle) {
switch (handle.getTag()) {
case Opcodes.H_GETFIELD:
case Opcodes.H_GETSTATIC:
case Opcodes.H_PUTFIELD:
case Opcodes.H_PUTSTATIC:
visitFieldInsn(Opcodes.GETFIELD, handle.getOwner(), handle.getName(), handle.getDesc());
break;
case Opcodes.H_INVOKEVIRTUAL:
case Opcodes.H_INVOKEINTERFACE:
case Opcodes.H_INVOKESPECIAL:
case Opcodes.H_INVOKESTATIC:
case Opcodes.H_NEWINVOKESPECIAL:
visitMethodInsn(
Opcodes.H_INVOKEVIRTUAL,
handle.getOwner(),
handle.getName(),
handle.getDesc(),
false);
createAdditionalMethodsForDesugar(handle);
break;
default:
throw new IllegalStateException(
"MethodHandle tag is not supported: " + handle.getTag());
}
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkMethodIdentifier(version, name, "name");
checkMethodDescriptor(version, descriptor);
if (bootstrapMethodHandle.getTag() != Opcodes.H_INVOKESTATIC
&& bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
throw new IllegalArgumentException("invalid handle tag " + bootstrapMethodHandle.getTag());
}
for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
checkLdcConstant(bootstrapMethodArgument);
}
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
++insnCount;
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkMethodIdentifier(version, name, "name");
checkMethodDescriptor(version, descriptor);
if (bootstrapMethodHandle.getTag() != Opcodes.H_INVOKESTATIC
&& bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
throw new IllegalArgumentException("invalid handle tag " + bootstrapMethodHandle.getTag());
}
for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
checkLdcConstant(bootstrapMethodArgument);
}
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
++insnCount;
}
private void createAdditionalMethodsForDesugar(Handle handle) {
visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
"-$$Lambda$" + handle.getOwner(),
"lambda$constructor$" + handle.getName(),
handle.getDesc(),
false);
visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
"-$$Lambda$" + handle.getOwner(),
"lambda$original$" + handle.getName(),
handle.getDesc(),
false);
visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
"-$$Lambda$" + handle.getOwner(),
"lambda$bridge$" + handle.getName(),
handle.getDesc(),
false);
if (!(handle.getTag() == Opcodes.H_INVOKEVIRTUAL
|| handle.getTag() == Opcodes.H_INVOKEINTERFACE)) {
visitMethodInsn(
Opcodes.INVOKESTATIC,
"-$$Lambda$" + handle.getOwner(),
"lambda$forwarding$" + handle.getName(),
handle.getDesc(),
false);
}
}
/**
* Returns the given value, remapped with this remapper. Possible values are {@link Boolean},
* {@link Byte}, {@link Short}, {@link Character}, {@link Integer}, {@link Long}, {@link Double},
* {@link Float}, {@link String}, {@link Type}, {@link Handle}, {@link ConstantDynamic} or arrays
* of primitive types .
*
* @param value an object. Only {@link Type}, {@link Handle} and {@link ConstantDynamic} values
* are remapped.
* @return the given value, remapped with this remapper.
*/
public Object mapValue(final Object value) {
if (value instanceof Type) {
return mapType((Type) value);
}
if (value instanceof Handle) {
Handle handle = (Handle) value;
return new Handle(
handle.getTag(),
mapType(handle.getOwner()),
mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
handle.getTag() <= Opcodes.H_PUTSTATIC
? mapDesc(handle.getDesc())
: mapMethodDesc(handle.getDesc()),
handle.isInterface());
}
if (value instanceof ConstantDynamic) {
ConstantDynamic constantDynamic = (ConstantDynamic) value;
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArgumentCount];
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
remappedBootstrapMethodArguments[i] =
mapValue(constantDynamic.getBootstrapMethodArgument(i));
}
String descriptor = constantDynamic.getDescriptor();
return new ConstantDynamic(
mapInvokeDynamicMethodName(constantDynamic.getName(), descriptor),
mapDesc(descriptor),
(Handle) mapValue(constantDynamic.getBootstrapMethod()),
remappedBootstrapMethodArguments);
}
return value;
}
/**
* Returns the given value, remapped with this remapper. Possible values are {@link Boolean},
* {@link Byte}, {@link Short}, {@link Character}, {@link Integer}, {@link Long}, {@link Double},
* {@link Float}, {@link String}, {@link Type}, {@link Handle}, {@link ConstantDynamic} or arrays
* of primitive types .
*
* @param value an object. Only {@link Type}, {@link Handle} and {@link ConstantDynamic} values
* are remapped.
* @return the given value, remapped with this remapper.
*/
public Object mapValue(final Object value) {
if (value instanceof Type) {
return mapType((Type) value);
}
if (value instanceof Handle) {
Handle handle = (Handle) value;
return new Handle(
handle.getTag(),
mapType(handle.getOwner()),
mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
handle.getTag() <= Opcodes.H_PUTSTATIC
? mapDesc(handle.getDesc())
: mapMethodDesc(handle.getDesc()),
handle.isInterface());
}
if (value instanceof ConstantDynamic) {
ConstantDynamic constantDynamic = (ConstantDynamic) value;
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArgumentCount];
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
remappedBootstrapMethodArguments[i] =
mapValue(constantDynamic.getBootstrapMethodArgument(i));
}
String descriptor = constantDynamic.getDescriptor();
return new ConstantDynamic(
mapInvokeDynamicMethodName(constantDynamic.getName(), descriptor),
mapDesc(descriptor),
(Handle) mapValue(constantDynamic.getBootstrapMethod()),
remappedBootstrapMethodArguments);
}
return value;
}
/**
* @param methodHandle The pre-transform method handle.
* @param mapMethodDescriptor True if the underlying descriptor should be mapped or false to leave it unchanged.
* @return The post-transform method handle.
*/
public Handle mapHandle(Handle methodHandle, boolean mapMethodDescriptor, boolean preserveDebuggability) {
String methodOwner = methodHandle.getOwner();
String methodName = methodHandle.getName();
String methodDescriptor = methodHandle.getDesc();
String newMethodOwner = mapType(methodOwner, preserveDebuggability);
String newMethodName = mapMethodName(methodName);
String newMethodDescriptor = mapMethodDescriptor ? mapDescriptor(methodDescriptor, preserveDebuggability) : methodDescriptor;
return new Handle(methodHandle.getTag(), newMethodOwner, newMethodName, newMethodDescriptor, methodHandle.isInterface());
}
private Handle newLambdaHandleFrom(Handle origHandle, boolean shadowMethodDescriptor) {
final String owner = origHandle.getOwner();
final String newOwner = owner;
final String newMethodName = origHandle.getName();
final String newMethodDescriptor = shadowMethodDescriptor ? replacer.replaceMethodDescriptor(origHandle.getDesc()) : origHandle.getDesc();
return new Handle(origHandle.getTag(), newOwner, newMethodName, newMethodDescriptor, origHandle.isInterface());
}
public Object mapValue(Object value) {
if (value instanceof Type) {
return mapType((Type) value);
}
if (value instanceof Handle) {
Handle h = (Handle) value;
return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
h.getOwner(), h.getName(), h.getDesc()),
mapMethodDesc(h.getDesc()));
}
return value;
}
/**
* Returns the given value, remapped with this remapper. Possible values are {@link Boolean},
* {@link Byte}, {@link Short}, {@link Character}, {@link Integer}, {@link Long}, {@link Double},
* {@link Float}, {@link String}, {@link Type}, {@link Handle}, {@link ConstantDynamic} or arrays
* of primitive types .
*
* @param value an object. Only {@link Type}, {@link Handle} and {@link ConstantDynamic} values
* are remapped.
* @return the given value, remapped with this remapper.
*/
public Object mapValue(final Object value) {
if (value instanceof Type) {
return mapType((Type) value);
}
if (value instanceof Handle) {
Handle handle = (Handle) value;
return new Handle(
handle.getTag(),
mapType(handle.getOwner()),
mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
handle.getTag() <= Opcodes.H_PUTSTATIC
? mapDesc(handle.getDesc())
: mapMethodDesc(handle.getDesc()),
handle.isInterface());
}
if (value instanceof ConstantDynamic) {
ConstantDynamic constantDynamic = (ConstantDynamic) value;
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArgumentCount];
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
remappedBootstrapMethodArguments[i] =
mapValue(constantDynamic.getBootstrapMethodArgument(i));
}
String descriptor = constantDynamic.getDescriptor();
return new ConstantDynamic(
mapInvokeDynamicMethodName(constantDynamic.getName(), descriptor),
mapDesc(descriptor),
(Handle) mapValue(constantDynamic.getBootstrapMethod()),
remappedBootstrapMethodArguments);
}
return value;
}
/**
* Appends a string representation of the given handle to {@link #stringBuilder}.
*
* @param handle a handle.
*/
protected void appendHandle(final Handle handle) {
int tag = handle.getTag();
stringBuilder.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
stringBuilder.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
stringBuilder.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
stringBuilder.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
stringBuilder.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
stringBuilder.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
stringBuilder.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
stringBuilder.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
stringBuilder.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
stringBuilder.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
stringBuilder.append(tab3);
appendDescriptor(INTERNAL_NAME, handle.getOwner());
stringBuilder.append('.');
stringBuilder.append(handle.getName());
if (!isMethodHandle) {
stringBuilder.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, handle.getDesc());
if (!isMethodHandle) {
stringBuilder.append(')');
}
if (handle.isInterface()) {
stringBuilder.append(" itf");
}
}
/**
* Appends the information about the given handle to {@link #buf buf}.
*
* @param h
* a handle, non null.
*/
protected void appendHandle(final Handle h) {
int tag = h.getTag();
buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
buf.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
buf.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
buf.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
buf.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
buf.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
buf.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
buf.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
buf.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
buf.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
}
buf.append('\n');
buf.append(tab3);
appendDescriptor(INTERNAL_NAME, h.getOwner());
buf.append('.');
buf.append(h.getName());
if (!isMethodHandle) {
buf.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
if (!isMethodHandle) {
buf.append(')');
}
if (h.isInterface()) {
buf.append(" itf");
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
Handle handle = (Handle) value;
int tag = handle.getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
checkInternalName(this.version, handle.getOwner(), "handle owner");
if (tag <= Opcodes.H_PUTSTATIC) {
checkDescriptor(this.version, handle.getDesc(), false);
} else {
checkMethodDescriptor(this.version, handle.getDesc());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "handle name");
}
} else if (value instanceof ConstantDynamic) {
if ((version & 0xFFFF) < Opcodes.V11) {
throw new IllegalArgumentException("ldc of a ConstantDynamic requires at least version 11");
}
ConstantDynamic constantDynamic = (ConstantDynamic) value;
checkMethodIdentifier(this.version, constantDynamic.getName(), "constant dynamic name");
checkDescriptor(this.version, constantDynamic.getDescriptor(), false);
checkLdcConstant(constantDynamic.getBootstrapMethod());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}
/**
* {@inheritDoc}
*
* @see org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn(java.lang.String, java.lang.String,
* org.objectweb.asm.Handle, java.lang.Object[])
*/
@Override
public void visitInvokeDynamicInsn ( String name, String desc, Handle bsm, Object... bsmArgs ) {
if ( bsm.getTag() == Opcodes.H_INVOKESTATIC
&& ( bsm.getName().equals("metafactory") || //$NON-NLS-1$
bsm.getName().equals("altMetafactory") ) //$NON-NLS-1$
&& bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory") && bsmArgs.length >= 2 ) { //$NON-NLS-1$
Handle h = (Handle) bsmArgs[ 1 ];
Type[] handleArgs = Type.getArgumentTypes(h.getDesc());
Type[] formalArgs = Type.getArgumentTypes(desc);
List<BaseType> args = this.stack.pop(formalArgs.length);
boolean tainted = checkTainted(formalArgs, args);
String className = Type.getObjectType(h.getOwner()).getClassName();
boolean isStatic = h.getTag() == Opcodes.H_INVOKESTATIC;
MethodReference r = new MethodReference(className, false, h.getName(), isStatic, h.getDesc());
this.foundRefs.add(r);
if ( tainted ) {
if ( !Arrays.equals(handleArgs, formalArgs) ) {
if ( this.log.isDebugEnabled() ) {
this.log.debug("Mismatch between formal args and handle args in " + this.ref + " " + name); //$NON-NLS-1$ //$NON-NLS-2$
this.log.debug("Handle arguments are " + Arrays.toString(handleArgs)); //$NON-NLS-1$
this.log.debug("Formal arguments are " + Arrays.toString(formalArgs)); //$NON-NLS-1$
this.log.debug("BSM arguments are " + Arrays.toString(bsmArgs)); //$NON-NLS-1$
}
this.parent.getAnalyzer().getState().getBench().unhandledLambda();
r.setArgumentTypes(setupTainting(r, Opcodes.INVOKEDYNAMIC, Collections.EMPTY_LIST, null, r, handleArgs));
}
else {
r.setArgumentTypes(setupTainting(r, Opcodes.INVOKEDYNAMIC, args, null, r, handleArgs));
}
this.parent.getAnalyzer().getState().getBench().taintedCall();
if ( this.log.isDebugEnabled() ) {
this.log.debug(String.format(
"In %s need to check lambda %s %s::%s %s (%s): %s", //$NON-NLS-1$
this.ref,
bsm.getTag(),
bsm.getOwner(),
bsm.getName(),
desc,
bsm.getDesc(),
Arrays.toString(bsmArgs)));
this.log.debug(String.format("In %s need to check lambda %s::%s (%s)", this.ref, h.getOwner(), h.getName(), h.getDesc())); //$NON-NLS-1$
this.log.debug("Arguments " + args); //$NON-NLS-1$
}
boolean unsafeCall = this.parent.getAnalyzer().checkMethodCall(r, Collections.singleton(this.ref), true, false);
if ( !unsafeCall ) {
this.log.debug("Call is safe"); //$NON-NLS-1$
}
this.foundCall = true;
}
else {
this.parent.getAnalyzer().getState().traceCalls(r, Collections.singleton(this.ref));
this.parent.getAnalyzer().getState().getBench().untaintedCall();
}
Type returnType = Type.getReturnType(desc);
if ( returnType != Type.VOID_TYPE ) {
this.stack.push(new BasicVariable(returnType, "return " + r, tainted)); //$NON-NLS-1$
}
}
else {
this.log.warn("Unsupported dynamic call in " + this.ref); //$NON-NLS-1$
this.log.warn(String.format(
"In %s need to check lambda %s %s::%s %s (%s): %s", //$NON-NLS-1$
this.ref,
bsm.getTag(),
bsm.getOwner(),
bsm.getName(),
desc,
bsm.getDesc(),
Arrays.toString(bsmArgs)));
}
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
/**
* Appends a string representation of the given handle to {@link #stringBuilder}.
*
* @param handle a handle.
*/
protected void appendHandle(final Handle handle) {
int tag = handle.getTag();
stringBuilder.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
stringBuilder.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
stringBuilder.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
stringBuilder.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
stringBuilder.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
stringBuilder.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
stringBuilder.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
stringBuilder.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
stringBuilder.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
stringBuilder.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
stringBuilder.append(tab3);
appendDescriptor(INTERNAL_NAME, handle.getOwner());
stringBuilder.append('.');
stringBuilder.append(handle.getName());
if (!isMethodHandle) {
stringBuilder.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, handle.getDesc());
if (!isMethodHandle) {
stringBuilder.append(')');
}
if (handle.isInterface()) {
stringBuilder.append(" itf");
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
Handle handle = (Handle) value;
int tag = handle.getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
checkInternalName(this.version, handle.getOwner(), "handle owner");
if (tag <= Opcodes.H_PUTSTATIC) {
checkDescriptor(this.version, handle.getDesc(), false);
} else {
checkMethodDescriptor(this.version, handle.getDesc());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "handle name");
}
} else if (value instanceof ConstantDynamic) {
if ((version & 0xFFFF) < Opcodes.V11) {
throw new IllegalArgumentException("ldc of a ConstantDynamic requires at least version 11");
}
ConstantDynamic constantDynamic = (ConstantDynamic) value;
checkMethodIdentifier(this.version, constantDynamic.getName(), "constant dynamic name");
checkDescriptor(this.version, constantDynamic.getDescriptor(), false);
checkLdcConstant(constantDynamic.getBootstrapMethod());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}