Пример #1
0
        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());
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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());
        }
Пример #5
0
        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);
        }