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[] GetIncomingStructure(ASInstance instance, ASMethod method) { if (method.Body.Exceptions.Count > 0) { return(null); } ASCode code = method.Body.ParseCode(); if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0) { return(null); } List <PacketValue> structure = new List <PacketValue>(); ABCFile abc = method.GetABC(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction.OP != OPCode.GetLocal_1) { continue; } ASInstruction next = code[++i]; switch (next.OP) { case OPCode.CallProperty: { CallPropertyIns callProperty = (CallPropertyIns)next; if (callProperty.ArgCount > 0) { ASMultiname propertyName = null; ASInstruction previous = code[i - 2]; switch (previous.OP) { case OPCode.GetLex: { GetLexIns getLex = (GetLexIns)previous; propertyName = getLex.TypeName; break; } case OPCode.ConstructProp: { ConstructPropIns constructProp = (ConstructPropIns)previous; propertyName = constructProp.PropertyName; break; } case OPCode.GetLocal_0: { propertyName = instance.QName; break; } } ASInstance innerInstance = abc.GetInstance(propertyName); ASMethod innerMethod = innerInstance.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); if (innerMethod == null) { ASClass innerClass = abc.GetClass(propertyName); innerMethod = innerClass.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); } PacketValue[] innerStructure = GetIncomingStructure(innerInstance, innerMethod); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); } else { if (!TryGetPacketValue(callProperty.PropertyName, null, out PacketValue piece)) { return(null); } structure.Add(piece); } break; } case OPCode.ConstructProp: { ConstructPropIns constructProp = (ConstructPropIns)next; ASInstance innerInstance = abc.GetInstance(constructProp.PropertyName); PacketValue[] innerStructure = GetIncomingStructure(innerInstance, innerInstance.Constructor); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); break; } case OPCode.ConstructSuper: { ASInstance superInstance = abc.GetInstance(instance.Super); PacketValue[] innerStructure = GetIncomingStructure(superInstance, superInstance.Constructor); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); break; } case OPCode.CallSuper: { CallSuperIns callSuper = (CallSuperIns)next; ASInstance superInstance = abc.GetInstance(instance.Super); ASMethod superMethod = superInstance.GetMethod(callSuper.MethodName.Name, null, callSuper.ArgCount); PacketValue[] innerStructure = GetIncomingStructure(superInstance, superMethod); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); break; } case OPCode.CallPropVoid: { CallPropVoidIns callPropVoid = (CallPropVoidIns)next; if (callPropVoid.ArgCount != 0) { return(null); } if (!TryGetPacketValue(callPropVoid.PropertyName, null, out PacketValue piece)) { return(null); } structure.Add(piece); break; } default: return(null); } } return(structure.Count == 0 ? null : structure.ToArray()); }
private List <HReference> FindMessageReferences(ASClass fromClass, ASContainer fromContainer, ASMethod fromMethod) { int instructionRank = 0; ABCFile abc = fromMethod.GetABC(); Stack <ASMultiname> nameStack = new Stack <ASMultiname>(); List <HReference> references = new List <HReference>(); ASContainer container = null; ASCode code = fromMethod.Body.ParseCode(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; switch (instruction.OP) { default: continue; case OPCode.NewFunction: { NewFunctionIns newFunction = (NewFunctionIns)instruction; references.AddRange(FindMessageReferences(fromClass, fromContainer, newFunction.Method)); continue; } case OPCode.GetProperty: { GetPropertyIns getProperty = (GetPropertyIns)instruction; nameStack.Push(getProperty.PropertyName); continue; } case OPCode.GetLex: { GetLexIns getLex = (GetLexIns)instruction; container = abc.GetClass(getLex.TypeName.Name); continue; } case OPCode.GetLocal_0: { container = fromContainer; continue; } case OPCode.ConstructProp: { ConstructPropIns constructProp = (ConstructPropIns)instruction; nameStack.Push(constructProp.PropertyName); break; } } ASMultiname messageQName = nameStack.Pop(); if (string.IsNullOrWhiteSpace(messageQName.Name)) { continue; } ASClass messageClass = abc.GetClass(messageQName.Name); if (messageClass == null) { continue; } if (!_messages.TryGetValue(messageClass, out HMessage message)) { continue; } if (message.References.Any(r => r.FromMethod == fromMethod)) { continue; } HReference reference = new HReference(); message.References.Add(reference); if (message.IsOutgoing) { reference.FromClass = fromClass; reference.FromMethod = fromMethod; reference.InstructionRank = ++instructionRank; reference.IsAnonymous = (!fromMethod.IsConstructor && fromMethod.Trait == null); references.Add(reference); } else { ASMultiname methodName = nameStack.Pop(); ASMethod callbackMethod = fromContainer.GetMethod(methodName.Name); if (callbackMethod == null) { callbackMethod = container.GetMethod(methodName.Name); if (callbackMethod == null) { ASMultiname slotName = nameStack.Pop(); ASTrait hostTrait = container.GetTraits(TraitKind.Slot) .FirstOrDefault(st => st.QName == slotName); container = abc.GetInstance(hostTrait.Type.Name); callbackMethod = container.GetMethod(methodName.Name); } } reference.FromMethod = callbackMethod; } } return(references); }
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); }
private string GetIncomingStructure(ASInstance instance, ASMethod method) { if (method.Body.Exceptions.Count > 0) { return(null); } ASCode code = method.Body.ParseCode(); if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0) { return(null); } string structure = null; ABCFile abc = method.GetABC(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction.OP != OPCode.GetLocal_1) { continue; } ASInstruction next = code[++i]; switch (next.OP) { case OPCode.CallProperty: { var callProperty = (CallPropertyIns)next; if (callProperty.ArgCount > 0) { ASMultiname propertyName = null; ASInstruction previous = code[i - 2]; switch (previous.OP) { case OPCode.GetLex: { var getLex = (GetLexIns)previous; propertyName = getLex.TypeName; break; } case OPCode.ConstructProp: { var constructProp = (ConstructPropIns)previous; propertyName = constructProp.PropertyName; break; } case OPCode.GetLocal_0: { propertyName = instance.QName; break; } } ASInstance innerInstance = abc.GetInstance(propertyName); ASMethod innerMethod = innerInstance.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); if (innerMethod == null) { ASClass innerClass = abc.GetClass(propertyName); innerMethod = innerClass.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); } string innerStructure = GetIncomingStructure(innerInstance, innerMethod); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; } else { if (!TryGetStructurePiece(callProperty.PropertyName, null, out char piece)) { return(null); } structure += piece; } break; } case OPCode.ConstructProp: { var constructProp = (ConstructPropIns)next; ASInstance innerInstance = abc.GetInstance(constructProp.PropertyName); string innerStructure = GetIncomingStructure(innerInstance, innerInstance.Constructor); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; break; } case OPCode.ConstructSuper: { ASInstance superInstance = abc.GetInstance(instance.Super); string innerStructure = GetIncomingStructure(superInstance, superInstance.Constructor); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; break; } case OPCode.CallSuper: { var callSuper = (CallSuperIns)next; ASInstance superInstance = abc.GetInstance(instance.Super); ASMethod superMethod = superInstance.GetMethod(callSuper.MethodName.Name, null, callSuper.ArgCount); string innerStructure = GetIncomingStructure(superInstance, superMethod); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; break; } case OPCode.CallPropVoid: { var callPropVoid = (CallPropVoidIns)next; if (callPropVoid.ArgCount != 0) { return(null); } if (!TryGetStructurePiece(callPropVoid.PropertyName, null, out char piece)) { return(null); } structure += piece; break; } default: return(null); } } return(structure); }