private PacketValue[] GetOutgoingStructure(ASCode code, Local getLocal) { List <PacketValue> structure = new List <PacketValue>(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction == getLocal) { break; } if (!Local.IsGetLocal(instruction.OP)) { continue; } Local local = (Local)instruction; if (local.Register != getLocal.Register) { continue; } for (i += 1; i < code.Count; i++) { ASInstruction next = code[i]; if (next.OP != OPCode.CallPropVoid) { continue; } CallPropVoidIns callPropVoid = (CallPropVoidIns)next; if (callPropVoid.PropertyName.Name != "push") { continue; } ASInstruction previous = code[i - 1]; if (previous.OP == OPCode.GetProperty) { ASClass classToCheck = Class; GetPropertyIns getProperty = (GetPropertyIns)previous; ASMultiname propertyName = getProperty.PropertyName; ASInstruction beforeGetProp = code[i - 2]; if (beforeGetProp.OP == OPCode.GetLex) { GetLexIns getLex = (GetLexIns)beforeGetProp; classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName); } if (!TryGetPacketValue(propertyName, classToCheck, out PacketValue piece)) { return(null); } structure.Add(piece); } } } return(structure.Count == 0 ? null : structure.ToArray()); }
private string GetOutgoingStructure(ASCode code, Local getLocal) { string structure = null; for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction == getLocal) { break; } if (!Local.IsGetLocal(instruction.OP)) { continue; } var local = (Local)instruction; if (local.Register != getLocal.Register) { continue; } for (i += 1; i < code.Count; i++) { ASInstruction next = code[i]; if (next.OP != OPCode.CallPropVoid) { continue; } var callPropVoid = (CallPropVoidIns)next; if (callPropVoid.PropertyName.Name != "push") { continue; } ASInstruction previous = code[i - 1]; if (previous.OP == OPCode.GetProperty) { ASClass classToCheck = Class; var getProperty = (GetPropertyIns)previous; ASMultiname propertyName = getProperty.PropertyName; ASInstruction beforeGetProp = code[i - 2]; if (beforeGetProp.OP == OPCode.GetLex) { var getLex = (GetLexIns)beforeGetProp; classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName); } if (!TryGetStructurePiece(propertyName, classToCheck, out char piece)) { return(null); } structure += piece; } } } return(structure); }
private PacketValue[] GetOutgoingStructure(ASCode code, ASInstruction beforeReturn, int length) { int getLocalEndIndex = -1; int pushingEndIndex = code.IndexOf(beforeReturn); PacketValue[] structure = new PacketValue[length]; Dictionary <int, int> pushedLocals = new Dictionary <int, int>(); for (int i = pushingEndIndex - 1; i >= 0; i--) { ASInstruction instruction = code[i]; if (instruction.OP == OPCode.GetProperty) { ASClass classToCheck = Class; GetPropertyIns getProperty = (GetPropertyIns)instruction; ASMultiname propertyName = getProperty.PropertyName; ASInstruction previous = code[i - 1]; if (previous.OP == OPCode.GetLex) { GetLexIns getLex = (GetLexIns)previous; classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName); } if (!TryGetPacketValue(propertyName, classToCheck, out PacketValue piece)) { return(null); } structure[--length] = piece; } else if (Local.IsGetLocal(instruction.OP) && instruction.OP != OPCode.GetLocal_0) { Local local = (Local)instruction; pushedLocals.Add(local.Register, --length); if (getLocalEndIndex == -1) { getLocalEndIndex = i; } } if (length == 0) { break; } } for (int i = getLocalEndIndex - 1; i >= 0; i--) { ASInstruction instruction = code[i]; if (!Local.IsSetLocal(instruction.OP)) { continue; } Local local = (Local)instruction; if (pushedLocals.TryGetValue(local.Register, out int structIndex)) { ASInstruction beforeSet = code[i - 1]; pushedLocals.Remove(local.Register); switch (beforeSet.OP) { case OPCode.PushInt: case OPCode.PushByte: case OPCode.Convert_i: structure[structIndex] = PacketValue.Integer; break; case OPCode.Coerce_s: case OPCode.PushString: structure[structIndex] = PacketValue.String; break; case OPCode.PushTrue: case OPCode.PushFalse: structure[structIndex] = PacketValue.Boolean; break; default: throw new Exception($"Don't know what this value type is, tell someone about this please.\r\nOP: {beforeSet.OP}"); } } if (pushedLocals.Count == 0) { break; } } return(structure); }
private PacketValue[] GetOutgoingStructure(ASClass @class, ASMultiname propertyName) { ASMethod constructor = @class.Instance.Constructor; if (constructor.Body.Exceptions.Count > 0) { return(null); } ASCode code = constructor.Body.ParseCode(); if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0) { return(null); } List <PacketValue> structure = new List <PacketValue>(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction.OP == OPCode.NewArray) { NewArrayIns newArray = (NewArrayIns)instruction; if (newArray.ArgCount > 0) { PacketValue[] structurePieces = new PacketValue[newArray.ArgCount]; for (int j = i - 1, length = newArray.ArgCount; j >= 0; j--) { ASInstruction previous = code[j]; if (Local.IsGetLocal(previous.OP) && previous.OP != OPCode.GetLocal_0) { Local local = (Local)previous; ASParameter parameter = constructor.Parameters[local.Register - 1]; if (!TryGetPacketValue(parameter.Type, null, out PacketValue piece)) { return(null); } structurePieces[--length] = piece; } if (length == 0) { structure.AddRange(structurePieces); break; } } } } else if (instruction.OP == OPCode.ConstructSuper) { ConstructSuperIns constructSuper = (ConstructSuperIns)instruction; if (constructSuper.ArgCount > 0) { ASClass superClass = @class.GetABC().GetClass(@class.Instance.Super); structure.AddRange(GetOutgoingStructure(superClass, propertyName)); } } if (instruction.OP != OPCode.GetProperty) { continue; } GetPropertyIns getProperty = (GetPropertyIns)instruction; if (getProperty.PropertyName != propertyName) { continue; } ASInstruction next = code[++i]; ASClass classToCheck = @class; if (Local.IsGetLocal(next.OP)) { if (next.OP == OPCode.GetLocal_0) { continue; } Local local = (Local)next; ASParameter parameter = constructor.Parameters[local.Register - 1]; if (!TryGetPacketValue(parameter.Type, null, out PacketValue piece)) { return(null); } structure.Add(piece); } else { if (next.OP == OPCode.FindPropStrict) { classToCheck = null; } else if (next.OP == OPCode.GetLex) { GetLexIns getLex = (GetLexIns)next; classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName); } do { next = code[++i]; propertyName = null; if (next.OP == OPCode.GetProperty) { getProperty = (GetPropertyIns)next; propertyName = getProperty.PropertyName; } else if (next.OP == OPCode.CallProperty) { CallPropertyIns callProperty = (CallPropertyIns)next; propertyName = callProperty.PropertyName; } }while (next.OP != OPCode.GetProperty && next.OP != OPCode.CallProperty); if (!TryGetPacketValue(propertyName, classToCheck, out PacketValue piece)) { return(null); } structure.Add(piece); } } return(structure.Count == 0 ? null : structure.ToArray()); }
private PacketValue[] GetOutgoingStructure(ASClass @class) { ASMethod getArrayMethod = @class.Instance.GetMethod(null, "Array", 0); if (getArrayMethod == null) { ASClass superClass = @class.GetABC().GetClass(@class.Instance.Super); return(GetOutgoingStructure(superClass)); } if (getArrayMethod.Body.Exceptions.Count > 0) { return(null); } ASCode getArrayCode = getArrayMethod.Body.ParseCode(); if (getArrayCode.JumpExits.Count > 0 || getArrayCode.SwitchExits.Count > 0) { // Unable to parse data structure that relies on user input that is not present, // since the structure may change based on the provided input. return(null); } ASInstruction resultPusher = null; for (int i = getArrayCode.Count - 1; i >= 0; i--) { ASInstruction instruction = getArrayCode[i]; if (instruction.OP == OPCode.ReturnValue) { resultPusher = getArrayCode[i - 1]; break; } } int argCount = -1; if (resultPusher.OP == OPCode.ConstructProp) { argCount = ((ConstructPropIns)resultPusher).ArgCount; } else if (resultPusher.OP == OPCode.NewArray) { argCount = ((NewArrayIns)resultPusher).ArgCount; } if (argCount > 0) { return(GetOutgoingStructure(getArrayCode, resultPusher, argCount)); } if (argCount == 0 || resultPusher.OP == OPCode.PushNull) { return(null); } if (resultPusher.OP == OPCode.GetProperty) { GetPropertyIns getProperty = (GetPropertyIns)resultPusher; return(GetOutgoingStructure(Class, getProperty.PropertyName)); } return(Local.IsGetLocal(resultPusher.OP) ? GetOutgoingStructure(getArrayCode, (Local)resultPusher) : null); }