Пример #1
0
			internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options, BigEndianBinaryReader br) : base(classFile, utf8_cp, br)
			{
				// vmspec 4.6 says that all flags, except ACC_STRICT are ignored on <clinit>
				// however, since Java 7 it does need to be marked static
				if(ReferenceEquals(Name, StringConstants.CLINIT) && ReferenceEquals(Signature, StringConstants.SIG_VOID) && (classFile.MajorVersion < 51 || IsStatic))
				{
					access_flags &= Modifiers.Strictfp;
					access_flags |= (Modifiers.Static | Modifiers.Private);
				}
				else
				{
					// LAMESPEC: vmspec 4.6 says that abstract methods can not be strictfp (and this makes sense), but
					// javac (pre 1.5) is broken and marks abstract methods as strictfp (if you put the strictfp on the class)
					if((ReferenceEquals(Name, StringConstants.INIT) && (IsStatic || IsSynchronized || IsFinal || IsAbstract || IsNative))
						|| (IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected)
						|| (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsSynchronized))
						|| (classFile.IsInterface && (!IsPublic || !IsAbstract)))
					{
						throw new ClassFormatError("{0} (Illegal method 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 "Code":
						{
							if(!code.IsEmpty)
							{
								throw new ClassFormatError("{0} (Duplicate Code attribute)", classFile.Name);
							}
							BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
							code.Read(classFile, utf8_cp, this, rdr, options);
							if(!rdr.IsAtEnd)
							{
								throw new ClassFormatError("{0} (Code attribute has wrong length)", classFile.Name);
							}
							break;
						}
						case "Exceptions":
						{
							if(exceptions != null)
							{
								throw new ClassFormatError("{0} (Duplicate Exceptions attribute)", classFile.Name);
							}
							BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
							ushort count = rdr.ReadUInt16();
							exceptions = new string[count];
							for(int j = 0; j < count; j++)
							{
								exceptions[j] = classFile.GetConstantPoolClass(rdr.ReadUInt16());
							}
							if(!rdr.IsAtEnd)
							{
								throw new ClassFormatError("{0} (Exceptions attribute has wrong length)", 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 "RuntimeVisibleParameterAnnotations":
						{
							if(classFile.MajorVersion < 49)
							{
								goto default;
							}
							if(low == null)
							{
								low = new LowFreqData();
							}
							BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
							byte num_parameters = rdr.ReadByte();
							low.parameterAnnotations = new object[num_parameters][];
							for(int j = 0; j < num_parameters; j++)
							{
								ushort num_annotations = rdr.ReadUInt16();
								low.parameterAnnotations[j] = new object[num_annotations];
								for(int k = 0; k < num_annotations; k++)
								{
									low.parameterAnnotations[j][k] = ReadAnnotation(rdr, classFile, utf8_cp);
								}
							}
							if(!rdr.IsAtEnd)
							{
								throw new ClassFormatError("{0} (RuntimeVisibleParameterAnnotations attribute has wrong length)", classFile.Name);
							}
							break;
						}
						case "AnnotationDefault":
						{
							if(classFile.MajorVersion < 49)
							{
								goto default;
							}
							if(low == null)
							{
								low = new LowFreqData();
							}
							BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
							low.annotationDefault = ReadAnnotationElementValue(rdr, classFile, utf8_cp);
							if(!rdr.IsAtEnd)
							{
								throw new ClassFormatError("{0} (AnnotationDefault attribute has wrong length)", classFile.Name);
							}
							break;
						}
#if STATIC_COMPILER
						case "RuntimeInvisibleAnnotations":
							if(classFile.MajorVersion < 49)
							{
								goto default;
							}
							foreach(object[] annot in ReadAnnotations(br, classFile, utf8_cp))
							{
								if(annot[1].Equals("Likvm/lang/Internal;"))
								{
									if (classFile.IsInterface)
									{
										StaticCompiler.IssueMessage(Message.InterfaceMethodCantBeInternal, classFile.Name, this.Name, this.Signature);
									}
									else
									{
										this.access_flags &= ~Modifiers.AccessMask;
										flags |= FLAG_MASK_INTERNAL;
									}
								}
								if(annot[1].Equals("Likvm/internal/HasCallerID;"))
								{
									flags |= FLAG_HAS_CALLERID;
								}
								if(annot[1].Equals("Likvm/lang/DllExport;"))
								{
									string name = null;
									int? ordinal = null;
									for (int j = 2; j < annot.Length; j += 2)
									{
										if (annot[j].Equals("name") && annot[j + 1] is string)
										{
											name = (string)annot[j + 1];
										}
										else if (annot[j].Equals("ordinal") && annot[j + 1] is int)
										{
											ordinal = (int)annot[j + 1];
										}
									}
									if (name != null && ordinal != null)
									{
										if (!IsStatic)
										{
											StaticCompiler.IssueMessage(Message.DllExportMustBeStaticMethod, classFile.Name, this.Name, this.Signature);
										}
										else
										{
											if (low == null)
											{
												low = new LowFreqData();
											}
											low.DllExportName = name;
											low.DllExportOrdinal = ordinal.Value;
										}
									}
								}
							}
							break;
#endif
						default:
							br.Skip(br.ReadUInt32());
							break;
					}
				}
				if(IsAbstract || IsNative)
				{
					if(!code.IsEmpty)
					{
						throw new ClassFormatError("Abstract or native method cannot have a Code attribute");
					}
				}
				else
				{
					if(code.IsEmpty)
					{
						if(ReferenceEquals(this.Name, StringConstants.CLINIT))
						{
							code.verifyError = string.Format("Class {0}, method {1} signature {2}: No Code attribute", classFile.Name, this.Name, this.Signature);
							return;
						}
						throw new ClassFormatError("Method has no Code attribute");
					}
				}
			}
Пример #2
0
		internal Method(ClassFile classFile, BigEndianBinaryReader br) : base(classFile, br)
		{
			// vmspec 4.6 says that all flags, except ACC_STRICT are ignored on <clinit>
			if (Name == "<clinit>" && Signature == "()V")
			{
				access_flags &= __Modifiers.Strictfp;
				access_flags |= (__Modifiers.Static | __Modifiers.Private);
			}
			else
			{
				// LAMESPEC: vmspec 4.6 says that abstract methods can not be strictfp (and this makes sense), but
				// javac (pre 1.5) is broken and marks abstract methods as strictfp (if you put the strictfp on the class)
				if ((Name == "<init>" && (IsStatic || IsSynchronized || IsFinal || IsAbstract || IsNative))
				    || (IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected)
				    || (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsSynchronized))
				    || (classFile.IsInterface && (!IsPublic || !IsAbstract)))
				{
					throw new ClassFormatError("{0} (Illegal method 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("{0} (Deprecated attribute has non-zero length)", classFile.Name);
						}
#endif
						break;
					case "Code":
						{
							if (!code.IsEmpty)
							{
								throw new ClassFormatError("{0} (Duplicate Code attribute)", classFile.Name);
							}
							BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
							code.Read(classFile, this, rdr);
							if (!rdr.IsAtEnd)
							{
								throw new ClassFormatError("{0} (Code attribute has wrong length)", classFile.Name);
							}
							break;
						}
					case "Exceptions":
						{
							if (exceptions != null)
							{
								throw new ClassFormatError("{0} (Duplicate Exceptions attribute)", classFile.Name);
							}
							BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
							ushort count = rdr.ReadUInt16();
							exceptions = new string[count];
							for (int j = 0; j < count; j++)
							{
								exceptions[j] = classFile.GetConstantPoolClass(rdr.ReadUInt16());
							}
							if (!rdr.IsAtEnd)
							{
								throw new ClassFormatError("{0} (Exceptions attribute has wrong length)", classFile.Name);
							}
							break;
						}
					default:
						br.Skip(br.ReadUInt32());
						break;
				}
			}
			if (IsAbstract || IsNative)
			{
				if (!code.IsEmpty)
				{
					throw new ClassFormatError("Abstract or native method cannot have a Code attribute");
				}
			}
			else
			{
				if (code.IsEmpty)
				{
#if FUZZ_HACK
					if (this.Name == "<clinit>")
					{
						code.verifyError = string.Format("Class {0}, method {1} signature {2}: No Code attribute", classFile.Name, this.Name, this.Signature);
						return;
					}
#endif
					throw new ClassFormatError("Method has no Code attribute");
				}
			}
		}