private static Exprent IsLambda(Exprent exprent, StructClass cl) { List <Exprent> lst = exprent.GetAllExprents(); foreach (Exprent expr in lst) { Exprent ret = IsLambda(expr, cl); if (ret != null) { exprent.ReplaceExprent(expr, ret); } } if (exprent.type == Exprent.Exprent_Invocation) { InvocationExprent @in = (InvocationExprent)exprent; if (@in.GetInvocationTyp() == InvocationExprent.Invoke_Dynamic) { string lambda_class_name = cl.qualifiedName + @in.GetInvokeDynamicClassSuffix(); ClassesProcessor.ClassNode lambda_class = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(lambda_class_name); if (lambda_class != null) { // real lambda class found, replace invocation with an anonymous class NewExprent newExpr = new NewExprent(new VarType(lambda_class_name, true), null, 0 , @in.bytecode); newExpr.SetConstructor(@in); // note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invocation // lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);) // in this case instance will hold the corresponding object return(newExpr); } } } return(null); }
private static Exprent IsSimpleConstructorInvocation(Exprent exprent) { List <Exprent> lst = exprent.GetAllExprents(); foreach (Exprent expr in lst) { Exprent ret = IsSimpleConstructorInvocation(expr); if (ret != null) { exprent.ReplaceExprent(expr, ret); } } if (exprent.type == Exprent.Exprent_Invocation) { InvocationExprent @in = (InvocationExprent)exprent; if (@in.GetFunctype() == InvocationExprent.Typ_Init && @in.GetInstance().type == Exprent.Exprent_New) { NewExprent newExpr = (NewExprent)@in.GetInstance(); newExpr.SetConstructor(@in); @in.SetInstance(null); return(newExpr); } } return(null); }
private static bool IsQualifiedNewGetClass(Exprent first, Exprent second) { if (first.type == Exprent.Exprent_Invocation) { InvocationExprent invocation = (InvocationExprent)first; if (!invocation.IsStatic() && invocation.GetInstance().type == Exprent.Exprent_Var && invocation.GetName().Equals("getClass") && invocation.GetStringDescriptor(). Equals("()Ljava/lang/Class;")) { List <Exprent> lstExprents = second.GetAllExprents(); lstExprents.Add(second); foreach (Exprent expr in lstExprents) { if (expr.type == Exprent.Exprent_New) { NewExprent newExpr = (NewExprent)expr; if (newExpr.GetConstructor() != null && !(newExpr.GetConstructor().GetLstParameters ().Count == 0) && newExpr.GetConstructor().GetLstParameters()[0].Equals(invocation .GetInstance())) { string classname = newExpr.GetNewType().value; ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(classname); if (node != null && node.type != ClassesProcessor.ClassNode.Class_Root) { return(true); } } } } } } return(false); }
private static bool AddArrayInitializer(Exprent first, Exprent second) { if (first.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)first; if (@as.GetRight().type == Exprent.Exprent_New && @as.GetLeft().type == Exprent.Exprent_Var) { NewExprent newExpr = (NewExprent)@as.GetRight(); if (!(newExpr.GetLstArrayElements().Count == 0)) { VarExprent arrVar = (VarExprent)@as.GetLeft(); if (second.type == Exprent.Exprent_Assignment) { AssignmentExprent aas = (AssignmentExprent)second; if (aas.GetLeft().type == Exprent.Exprent_Array) { ArrayExprent arrExpr = (ArrayExprent)aas.GetLeft(); if (arrExpr.GetArray().type == Exprent.Exprent_Var && arrVar.Equals(arrExpr.GetArray ()) && arrExpr.GetIndex().type == Exprent.Exprent_Const) { int constValue = ((ConstExprent)arrExpr.GetIndex()).GetIntValue(); if (constValue < newExpr.GetLstArrayElements().Count) { Exprent init = newExpr.GetLstArrayElements()[constValue]; if (init.type == Exprent.Exprent_Const) { ConstExprent cinit = (ConstExprent)init; VarType arrType = newExpr.GetNewType().DecreaseArrayDim(); ConstExprent defaultVal = ExprProcessor.GetDefaultArrayValue(arrType); if (cinit.Equals(defaultVal)) { Exprent tempExpr = aas.GetRight(); if (!tempExpr.ContainsExprent(arrVar)) { newExpr.GetLstArrayElements()[constValue] = tempExpr; if (tempExpr.type == Exprent.Exprent_New) { NewExprent tempNewExpr = (NewExprent)tempExpr; int dims = newExpr.GetNewType().arrayDim; if (dims > 1 && !(tempNewExpr.GetLstArrayElements().Count == 0)) { tempNewExpr.SetDirectArrayInit(true); } } return(true); } } } } } } } } } } return(false); }
private static bool IsNewConcat(NewExprent expr, VarType cltype) { if (expr.GetNewType().Equals(cltype)) { VarType[] @params = expr.GetConstructor().GetDescriptor().@params; return(@params.Length == 0 || @params.Length == 1 && @params[0].Equals(VarType.Vartype_String )); } return(false); }
// propagate (var = new X) forward to the <init> invocation private static bool IsConstructorInvocationRemote(List <Exprent> list, int index) { Exprent current = list[index]; if (current.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)current; if (@as.GetLeft().type == Exprent.Exprent_Var && @as.GetRight().type == Exprent.Exprent_New) { NewExprent newExpr = (NewExprent)@as.GetRight(); VarType newType = newExpr.GetNewType(); VarVersionPair leftPair = new VarVersionPair((VarExprent)@as.GetLeft()); if (newType.type == ICodeConstants.Type_Object && newType.arrayDim == 0 && newExpr .GetConstructor() == null) { for (int i = index + 1; i < list.Count; i++) { Exprent remote = list[i]; // <init> invocation if (remote.type == Exprent.Exprent_Invocation) { InvocationExprent @in = (InvocationExprent)remote; if (@in.GetFunctype() == InvocationExprent.Typ_Init && @in.GetInstance().type == Exprent.Exprent_Var && @as.GetLeft().Equals(@in.GetInstance())) { newExpr.SetConstructor(@in); @in.SetInstance(null); list[i] = @as.Copy(); return(true); } } // check for variable in use HashSet <VarVersionPair> setVars = remote.GetAllVariables(); if (setVars.Contains(leftPair)) { // variable used somewhere in between -> exit, need a better reduced code return(false); } } } } } return(false); }
static ClassReference14Processor() { InvocationExprent invFor = new InvocationExprent(); invFor.SetName("forName"); invFor.SetClassname("java/lang/Class"); invFor.SetStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"); invFor.SetDescriptor(MethodDescriptor.ParseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;" )); invFor.SetStatic(true); invFor.SetLstParameters(new [] { new VarExprent(0, VarType .Vartype_String, null) }.Cast <Exprent>().ToList()); Body_Expr = new ExitExprent(ExitExprent.Exit_Return, invFor, VarType.Vartype_Class , null); InvocationExprent ctor = new InvocationExprent(); ctor.SetName(ICodeConstants.Init_Name); ctor.SetClassname("java/lang/NoClassDefFoundError"); ctor.SetStringDescriptor("()V"); ctor.SetFunctype(InvocationExprent.Typ_Init); ctor.SetDescriptor(MethodDescriptor.ParseDescriptor("()V")); NewExprent newExpr = new NewExprent(new VarType(ICodeConstants.Type_Object, 0, "java/lang/NoClassDefFoundError" ), new List <Exprent>(), null); newExpr.SetConstructor(ctor); InvocationExprent invCause = new InvocationExprent(); invCause.SetName("initCause"); invCause.SetClassname("java/lang/NoClassDefFoundError"); invCause.SetStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"); invCause.SetDescriptor(MethodDescriptor.ParseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;" )); invCause.SetInstance(newExpr); invCause.SetLstParameters(new List <Exprent>(new [] { new VarExprent(2, new VarType(ICodeConstants.Type_Object, 0, "java/lang/ClassNotFoundException"), null) }.ToList())); Handler_Expr = new ExitExprent(ExitExprent.Exit_Throw, invCause, null, null); }
private static InvocationExprent IsAssertionError(Statement stat) { if (stat == null || stat.GetExprents() == null || stat.GetExprents().Count != 1) { return(null); } Exprent expr = stat.GetExprents()[0]; if (expr.type == Exprent.Exprent_Exit) { ExitExprent exexpr = (ExitExprent)expr; if (exexpr.GetExitType() == ExitExprent.Exit_Throw && exexpr.GetValue().type == Exprent .Exprent_New) { NewExprent nexpr = (NewExprent)exexpr.GetValue(); if (Class_Assertion_Error.Equals(nexpr.GetNewType()) && nexpr.GetConstructor() != null) { return(nexpr.GetConstructor()); } } } return(null); }
private int[] IterateExprent(List <Exprent> lstExprents, int index, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { Exprent exprent = lstExprents[index]; int changed = 0; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, exprent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1] ? 1 : 0; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = 1; } if (!isReplaceable) { break; } } } // no var on the highest level, so no replacing VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new int[] { -1, changed }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { if (left.IsStack() && (right.type == Exprent.Exprent_Invocation || right.type == Exprent.Exprent_Assignment || right.type == Exprent.Exprent_New)) { if (right.type == Exprent.Exprent_New) { // new Object(); permitted NewExprent nexpr = (NewExprent)right; if (nexpr.IsAnonymous() || nexpr.GetNewType().arrayDim > 0 || nexpr.GetNewType(). type != ICodeConstants.Type_Object) { return(new int[] { -1, changed }); } } lstExprents[index] = right; return(new int[] { index + 1, 1 }); } else if (right.type == Exprent.Exprent_Var) { lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else { return(new int[] { -1, changed }); } } int useflags = right.GetExprentUse(); // stack variables only if (!left.IsStack() && (right.type != Exprent.Exprent_Var || ((VarExprent)right). IsStack())) { // special case catch(... ex) return(new int[] { -1, changed }); } if ((useflags & Exprent.Multiple_Uses) == 0 && (notdom || usedVers.Count > 1)) { return(new int[] { -1, changed }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); bool isSelfReference = mapVars.ContainsKey(leftpaar.var); if (isSelfReference && notdom) { return(new int[] { -1, changed }); } HashSet <VarVersionPair> setNextVars = next == null ? null : GetAllVersions(next); // FIXME: fix the entire method! if (right.type != Exprent.Exprent_Const && right.type != Exprent.Exprent_Var && setNextVars != null && mapVars.ContainsKey(leftpaar.var)) { foreach (VarVersionNode usedvar in usedVers) { if (!setNextVars.Contains(new VarVersionPair(usedvar.var, usedvar.version))) { return(new int[] { -1, changed }); } } } Sharpen.Collections.Remove(mapVars, leftpaar.var); bool vernotreplaced = false; bool verreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Const || right.type == Exprent.Exprent_Var || right.type == Exprent.Exprent_Field || setNextVars == null || setNextVars.Contains(usedver))) { setTempUsedVers.Add(usedver); verreplaced = true; } else { vernotreplaced = true; } } if (isSelfReference && vernotreplaced) { return(new int[] { -1, changed }); } else { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } } if (!notdom && !vernotreplaced) { // remove assignment lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else if (verreplaced) { return(new int[] { index + 1, changed }); } else { return(new int[] { -1, changed }); } }
private static int IsArrayInitializer(List <Exprent> list, int index) { Exprent current = list[index]; if (current.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)current; if (@as.GetRight().type == Exprent.Exprent_New && @as.GetLeft().type == Exprent.Exprent_Var) { NewExprent newExpr = (NewExprent)@as.GetRight(); if (newExpr.GetExprType().arrayDim > 0 && newExpr.GetLstDims().Count == 1 && (newExpr .GetLstArrayElements().Count == 0) && newExpr.GetLstDims()[0].type == Exprent.Exprent_Const) { int size = (int)((ConstExprent)newExpr.GetLstDims()[0]).GetValue(); if (size == 0) { return(0); } VarExprent arrVar = (VarExprent)@as.GetLeft(); Dictionary <int, Exprent> mapInit = new Dictionary <int, Exprent>(); int i = 1; while (index + i < list.Count && i <= size) { bool found = false; Exprent expr = list[index + i]; if (expr.type == Exprent.Exprent_Assignment) { AssignmentExprent aas = (AssignmentExprent)expr; if (aas.GetLeft().type == Exprent.Exprent_Array) { ArrayExprent arrExpr = (ArrayExprent)aas.GetLeft(); if (arrExpr.GetArray().type == Exprent.Exprent_Var && arrVar.Equals(arrExpr.GetArray ()) && arrExpr.GetIndex().type == Exprent.Exprent_Const) { // TODO: check for a number type. Failure extremely improbable, but nevertheless... int constValue = ((ConstExprent)arrExpr.GetIndex()).GetIntValue(); if (constValue < size && !mapInit.ContainsKey(constValue)) { if (!aas.GetRight().ContainsExprent(arrVar)) { Sharpen.Collections.Put(mapInit, constValue, aas.GetRight()); found = true; } } } } } if (!found) { break; } i++; } double fraction = ((double)mapInit.Count) / size; if ((arrVar.IsStack() && fraction > 0) || (size <= 7 && fraction >= 0.3) || (size > 7 && fraction >= 0.7)) { List <Exprent> lstRet = new List <Exprent>(); VarType arrayType = newExpr.GetNewType().DecreaseArrayDim(); ConstExprent defaultVal = ExprProcessor.GetDefaultArrayValue(arrayType); for (int j = 0; j < size; j++) { lstRet.Add(defaultVal.Copy()); } int dims = newExpr.GetNewType().arrayDim; foreach (KeyValuePair <int, Exprent> ent in mapInit) { Exprent tempExpr = ent.Value; lstRet[ent.Key] = tempExpr; if (tempExpr.type == Exprent.Exprent_New) { NewExprent tempNewExpr = (NewExprent)tempExpr; if (dims > 1 && !(tempNewExpr.GetLstArrayElements().Count == 0)) { tempNewExpr.SetDirectArrayInit(true); } } } newExpr.SetLstArrayElements(lstRet); return(mapInit.Count); } } } } return(0); }
/// <exception cref="IOException"/> public static Exprent ParseAnnotationElement(DataInputStream data, ConstantPool pool ) { int tag = data.ReadUnsignedByte(); switch (tag) { case 'e': { // enum constant string className = pool.GetPrimitiveConstant(data.ReadUnsignedShort()).GetString( ); string constName = pool.GetPrimitiveConstant(data.ReadUnsignedShort()).GetString( ); FieldDescriptor descr = FieldDescriptor.ParseDescriptor(className); return(new FieldExprent(constName, descr.type.value, true, null, descr, null)); } case 'c': { // class string descriptor = pool.GetPrimitiveConstant(data.ReadUnsignedShort()).GetString (); VarType type = FieldDescriptor.ParseDescriptor(descriptor).type; string value; switch (type.type) { case ICodeConstants.Type_Object: { value = type.value; break; } case ICodeConstants.Type_Byte: { value = typeof(byte).FullName; break; } case ICodeConstants.Type_Char: { value = typeof(char).FullName; break; } case ICodeConstants.Type_Double: { value = typeof(double).FullName; break; } case ICodeConstants.Type_Float: { value = typeof(float).FullName; break; } case ICodeConstants.Type_Int: { value = typeof(int).FullName; break; } case ICodeConstants.Type_Long: { value = typeof(long).FullName; break; } case ICodeConstants.Type_Short: { value = typeof(short).FullName; break; } case ICodeConstants.Type_Boolean: { value = typeof(bool).FullName; break; } case ICodeConstants.Type_Void: { value = typeof(void).FullName; break; } default: { throw new Exception("invalid class type: " + type.type); } } return(new ConstExprent(VarType.Vartype_Class, value, null)); } case '[': { // array List <Exprent> elements = new System.Collections.Generic.List <Exprent>(); int len = data.ReadUnsignedShort(); if (len > 0) { elements = new List <Exprent>(len); for (int i = 0; i < len; i++) { elements.Add(ParseAnnotationElement(data, pool)); } } VarType newType; if ((elements.Count == 0)) { newType = new VarType(ICodeConstants.Type_Object, 1, "java/lang/Object"); } else { VarType elementType = elements[0].GetExprType(); newType = new VarType(elementType.type, 1, elementType.value); } NewExprent newExpr = new NewExprent(newType, new System.Collections.Generic.List < Exprent>(), null); newExpr.SetDirectArrayInit(true); newExpr.SetLstArrayElements(elements); return(newExpr); } case '@': { // annotation return(ParseAnnotation(data, pool)); } default: { PrimitiveConstant cn = pool.GetPrimitiveConstant(data.ReadUnsignedShort()); switch (tag) { case 'B': { return(new ConstExprent(VarType.Vartype_Byte, cn.value, null)); } case 'C': { return(new ConstExprent(VarType.Vartype_Char, cn.value, null)); } case 'D': { return(new ConstExprent(VarType.Vartype_Double, cn.value, null)); } case 'F': { return(new ConstExprent(VarType.Vartype_Float, cn.value, null)); } case 'I': { return(new ConstExprent(VarType.Vartype_Int, cn.value, null)); } case 'J': { return(new ConstExprent(VarType.Vartype_Long, cn.value, null)); } case 'S': { return(new ConstExprent(VarType.Vartype_Short, cn.value, null)); } case 'Z': { return(new ConstExprent(VarType.Vartype_Boolean, cn.value, null)); } case 's': { return(new ConstExprent(VarType.Vartype_String, cn.value, null)); } default: { throw new Exception("invalid element type!"); } } break; } } }
public static Exprent ContractStringConcat(Exprent expr) { Exprent exprTmp = null; VarType cltype = null; // first quick test if (expr.type == Exprent.Exprent_Invocation) { InvocationExprent iex = (InvocationExprent)expr; if ("toString".Equals(iex.GetName())) { if (builderClass.Equals(iex.GetClassname())) { cltype = builderType; } else if (bufferClass.Equals(iex.GetClassname())) { cltype = bufferType; } if (cltype != null) { exprTmp = iex.GetInstance(); } } else if ("makeConcatWithConstants".Equals(iex.GetName())) { // java 9 style List <Exprent> parameters = ExtractParameters(iex.GetBootstrapArguments(), iex); if (parameters.Count >= 2) { return(CreateConcatExprent(parameters, expr.bytecode)); } } } if (exprTmp == null) { return(expr); } // iterate in depth, collecting possible operands List <Exprent> lstOperands = new List <Exprent>(); while (true) { int found = 0; switch (exprTmp.type) { case Exprent.Exprent_Invocation: { InvocationExprent iex = (InvocationExprent)exprTmp; if (IsAppendConcat(iex, cltype)) { lstOperands.Add(0, iex.GetLstParameters()[0]); exprTmp = iex.GetInstance(); found = 1; } break; } case Exprent.Exprent_New: { NewExprent nex = (NewExprent)exprTmp; if (IsNewConcat(nex, cltype)) { VarType[] @params = nex.GetConstructor().GetDescriptor().@params; if (@params.Length == 1) { lstOperands.Add(0, nex.GetConstructor().GetLstParameters()[0]); } found = 2; } break; } } if (found == 0) { return(expr); } else if (found == 2) { break; } } int first2str = 0; int index = 0; while (index < lstOperands.Count && index < 2) { if (lstOperands[index].GetExprType().Equals(VarType.Vartype_String)) { first2str |= (index + 1); } index++; } if (first2str == 0) { lstOperands.Add(0, new ConstExprent(VarType.Vartype_String, string.Empty, expr.bytecode )); } // remove redundant String.valueOf for (int i = 0; i < lstOperands.Count; i++) { Exprent rep = RemoveStringValueOf(lstOperands[i]); bool ok = (i > 1); if (!ok) { bool isstr = rep.GetExprType().Equals(VarType.Vartype_String); ok = isstr || first2str != i + 1; if (i == 0) { first2str &= 2; } } if (ok) { lstOperands[i] = rep; } } return(CreateConcatExprent(lstOperands, expr.bytecode)); }