private static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos)
        {
            if (bsm.ArgumentCount - argpos < 1)
            {
                return(false);
            }
            if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos)) != ClassFile.ConstantType.Integer)
            {
                return(false);
            }
            int count = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++));

            if (count < 0 || bsm.ArgumentCount - argpos < count)
            {
                return(false);
            }
            for (int i = 0; i < count; i++)
            {
                if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos++)) != type)
                {
                    return(false);
                }
            }
            return(true);
        }
        private static bool IsLambdaAltMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm)
        {
            ClassFile.ConstantPoolItemMethodHandle mh;
            AltFlags flags;
            int      argpos = 4;

            return(bsm.ArgumentCount >= 4 &&
                   (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic &&
                   IsLambdaAltMetafactory(mh.Member) &&
                   classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType &&
                   classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle &&
                   classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType &&
                   classFile.GetConstantPoolConstantType(bsm.GetArgument(3)) == ClassFile.ConstantType.Integer &&
                   ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3))) & ~AltFlags.Mask) == 0 &&
                   ((flags & AltFlags.Markers) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.Class, ref argpos)) &&
                   ((flags & AltFlags.Bridges) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.MethodType, ref argpos)) &&
                   argpos == bsm.ArgumentCount);
        }
        private bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen)
        {
            if (HasUnloadable(cpi))
            {
                Fail("cpi has unloadable");
                return(false);
            }
            bool serializable = false;

            TypeWrapper[] markers = TypeWrapper.EmptyArray;
            ClassFile.ConstantPoolItemMethodType[] bridges = null;
            if (bsm.ArgumentCount > 3)
            {
                AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3));
                serializable = (flags & AltFlags.Serializable) != 0;
                int argpos = 4;
                if ((flags & AltFlags.Markers) != 0)
                {
                    markers = new TypeWrapper[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))];
                    for (int i = 0; i < markers.Length; i++)
                    {
                        if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable)
                        {
                            Fail("unloadable marker");
                            return(false);
                        }
                    }
                }
                if ((flags & AltFlags.Bridges) != 0)
                {
                    bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))];
                    for (int i = 0; i < bridges.Length; i++)
                    {
                        bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++));
                        if (HasUnloadable(bridges[i]))
                        {
                            Fail("unloadable bridge");
                            return(false);
                        }
                    }
                }
            }
            ClassFile.ConstantPoolItemMethodType   samMethodType          = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0));
            ClassFile.ConstantPoolItemMethodHandle implMethod             = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1));
            ClassFile.ConstantPoolItemMethodType   instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2));
            if (HasUnloadable(samMethodType) ||
                HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem) ||
                HasUnloadable(instantiatedMethodType))
            {
                Fail("bsm args has unloadable");
                return(false);
            }
            TypeWrapper interfaceType = cpi.GetRetType();

            MethodWrapper[] methodList;
            if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList))
            {
                Fail("unsupported interface");
                return(false);
            }
            if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return(mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"); }))
            {
                Fail("writeReplace");
                return(false);
            }
            if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType))
            {
                Fail("implMethod " + implMethod.MemberConstantPoolItem.Class + "::" + implMethod.MemberConstantPoolItem.Name + implMethod.MemberConstantPoolItem.Signature);
                return(false);
            }
            TypeWrapper[] implParameters = GetImplParameters(implMethod);
            CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters);
            if (bridges != null)
            {
                foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges)
                {
                    if (bridge.Signature == samMethodType.Signature)
                    {
                        Fail("bridge signature matches sam");
                        return(false);
                    }
                    if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters))
                    {
                        Fail("bridge constraints");
                        return(false);
                    }
                }
            }
            if (instantiatedMethodType.GetRetType() != PrimitiveTypeWrapper.VOID)
            {
                TypeWrapper Rt = instantiatedMethodType.GetRetType();
                TypeWrapper Ra = GetImplReturnType(implMethod);
                if (Ra == PrimitiveTypeWrapper.VOID || !IsAdaptable(Ra, Rt, true))
                {
                    Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt");
                    return(false);
                }
            }
            MethodWrapper        interfaceMethod = null;
            List <MethodWrapper> methods         = new List <MethodWrapper>();

            foreach (MethodWrapper mw in methodList)
            {
                if (mw.Name == cpi.Name && mw.Signature == samMethodType.Signature)
                {
                    interfaceMethod = mw;
                    methods.Add(mw);
                }
                else if (mw.IsAbstract && !IsObjectMethod(mw))
                {
                    methods.Add(mw);
                }
            }
            if (interfaceMethod == null || !interfaceMethod.IsAbstract || IsObjectMethod(interfaceMethod) || !MatchSignatures(interfaceMethod, samMethodType))
            {
                Fail("interfaceMethod");
                return(false);
            }

            TypeBuilder tb = context.DefineAnonymousClass();

            // we're not implementing the interfaces recursively (because we don't care about .NET Compact anymore),
            // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is
            tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType);
            if (serializable && Array.IndexOf(markers, CoreClasses.java.io.Serializable.Wrapper) == -1)
            {
                tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType);
            }
            foreach (TypeWrapper marker in markers)
            {
                tb.AddInterfaceImplementation(marker.TypeAsBaseType);
            }
            ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable);
            AddDefaultInterfaceMethods(context, methodList, tb);
            return(true);
        }
			internal Field(ClassFile classFile, string[] utf8_cp, BigEndianBinaryReader br) : base(classFile, utf8_cp, br)
			{
				if((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected)
					|| (IsFinal && IsVolatile)
					|| (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient)))
				{
					throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, access_flags);
				}
				int attributes_count = br.ReadUInt16();
				for(int i = 0; i < attributes_count; i++)
				{
					switch(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()))
					{
						case "Deprecated":
							if(br.ReadUInt32() != 0)
							{
								throw new ClassFormatError("Invalid Deprecated attribute length");
							}
							flags |= FLAG_MASK_DEPRECATED;
							break;
						case "ConstantValue":
						{
							if(br.ReadUInt32() != 2)
							{
								throw new ClassFormatError("Invalid ConstantValue attribute length");
							}
							ushort index = br.ReadUInt16();
							try
							{
								switch(Signature)
								{
									case "I":
										constantValue = classFile.GetConstantPoolConstantInteger(index);
										break;
									case "S":
										constantValue = (short)classFile.GetConstantPoolConstantInteger(index);
										break;
									case "B":
										constantValue = (byte)classFile.GetConstantPoolConstantInteger(index);
										break;
									case "C":
										constantValue = (char)classFile.GetConstantPoolConstantInteger(index);
										break;
									case "Z":
										constantValue = classFile.GetConstantPoolConstantInteger(index) != 0;
										break;
									case "J":
										constantValue = classFile.GetConstantPoolConstantLong(index);
										break;
									case "F":
										constantValue = classFile.GetConstantPoolConstantFloat(index);
										break;
									case "D":
										constantValue = classFile.GetConstantPoolConstantDouble(index);
										break;
									case "Ljava.lang.String;":
										constantValue = classFile.GetConstantPoolConstantString(index);
										break;
									default:
										throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name);
								}
							}
							catch(InvalidCastException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							catch(IndexOutOfRangeException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							catch(InvalidOperationException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							catch(NullReferenceException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							break;
						}
						case "Signature":
							if(classFile.MajorVersion < 49)
							{
								goto default;
							}
							if(br.ReadUInt32() != 2)
							{
								throw new ClassFormatError("Signature attribute has incorrect length");
							}
							signature = classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16());
							break;
						case "RuntimeVisibleAnnotations":
							if(classFile.MajorVersion < 49)
							{
								goto default;
							}
							annotations = ReadAnnotations(br, classFile, utf8_cp);
							break;
						case "RuntimeInvisibleAnnotations":
							if(classFile.MajorVersion < 49)
							{
								goto default;
							}
							foreach(object[] annot in ReadAnnotations(br, classFile, utf8_cp))
							{
								if(annot[1].Equals("Likvm/lang/Property;"))
								{
									DecodePropertyAnnotation(classFile, annot);
								}
#if STATIC_COMPILER
								else if(annot[1].Equals("Likvm/lang/Internal;"))
								{
									this.access_flags &= ~Modifiers.AccessMask;
									flags |= FLAG_MASK_INTERNAL;
								}
#endif
							}
							break;
						default:
							br.Skip(br.ReadUInt32());
							break;
					}
				}
			}
Example #5
0
		internal Field(ClassFile classFile, BigEndianBinaryReader br) : base(classFile, br)
		{
			if ((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected)
			    || (IsFinal && IsVolatile)
			    || (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient)))
			{
				throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, access_flags);
			}
			int attributes_count = br.ReadUInt16();
			for (int i = 0; i < attributes_count; i++)
			{
				switch (classFile.GetConstantPoolUtf8String(br.ReadUInt16()))
				{
					case "Deprecated":
						deprecated = true;
#if FUZZ_HACK
						br.Skip(br.ReadUInt32());
#else
						if(br.ReadUInt32() != 0)
						{
							throw new ClassFormatError("Deprecated attribute has non-zero length");
						}
#endif
						break;
					case "ConstantValue":
						{
							if (br.ReadUInt32() != 2)
							{
								throw new ClassFormatError("Invalid ConstantValue attribute length");
							}
							ushort index = br.ReadUInt16();
							try
							{
								switch (Signature)
								{
									case "I":
										constantValue = classFile.GetConstantPoolConstantInteger(index);
										break;
									case "S":
										constantValue = (short) classFile.GetConstantPoolConstantInteger(index);
										break;
									case "B":
										constantValue = (byte) classFile.GetConstantPoolConstantInteger(index);
										break;
									case "C":
										constantValue = (char) classFile.GetConstantPoolConstantInteger(index);
										break;
									case "Z":
										constantValue = classFile.GetConstantPoolConstantInteger(index) != 0;
										break;
									case "J":
										constantValue = classFile.GetConstantPoolConstantLong(index);
										break;
									case "F":
										constantValue = classFile.GetConstantPoolConstantFloat(index);
										break;
									case "D":
										constantValue = classFile.GetConstantPoolConstantDouble(index);
										break;
									case "Ljava.lang.String;":
										constantValue = classFile.GetConstantPoolConstantString(index);
										break;
									default:
										throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name);
								}
							}
							catch (InvalidCastException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							catch (IndexOutOfRangeException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							catch (InvalidOperationException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							catch (NullReferenceException)
							{
								throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name);
							}
							break;
						}
					default:
						br.Skip(br.ReadUInt32());
						break;
				}
			}
		}