Example #1
0
        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());
        }
Example #2
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());
        }