Esempio n. 1
0
    public static java.lang.Class defineClass1(java.lang.ClassLoader thisClassLoader, string name, byte[] b, int off, int len, java.security.ProtectionDomain pd, string source)
    {
        // it appears the source argument is only used for trace messages in HotSpot. We'll just ignore it for now.
        Profiler.Enter("ClassLoader.defineClass");
        try
        {
            try
            {
                ClassLoaderWrapper    classLoaderWrapper = ClassLoaderWrapper.GetClassLoaderWrapper(thisClassLoader);
                ClassFileParseOptions cfp = ClassFileParseOptions.LineNumberTable;
                if (classLoaderWrapper.EmitDebugInfo)
                {
                    cfp |= ClassFileParseOptions.LocalVariableTable;
                }
                if (classLoaderWrapper.RelaxedClassNameValidation)
                {
                    cfp |= ClassFileParseOptions.RelaxedClassNameValidation;
                }
                ClassFile classFile = new ClassFile(b, off, len, name, cfp);
                if (name != null && classFile.Name != name)
                {
#if !FIRST_PASS
                    throw new java.lang.NoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")");
#endif
                }
                TypeWrapper type = classLoaderWrapper.DefineClass(classFile, pd);
                return(type.ClassObject);
            }
            catch (RetargetableJavaException x)
            {
                throw x.ToJava();
            }
        }
        finally
        {
            Profiler.Leave("ClassLoader.defineClass");
        }
    }
Esempio n. 2
0
				internal void Read(ClassFile classFile, string[] utf8_cp, Method method, BigEndianBinaryReader br, ClassFileParseOptions options)
				{
					max_stack = br.ReadUInt16();
					max_locals = br.ReadUInt16();
					uint code_length = br.ReadUInt32();
					if(code_length > 65535)
					{
						throw new ClassFormatError("{0} (Invalid Code length {1})", classFile.Name, code_length);
					}
					Instruction[] instructions = new Instruction[code_length + 1];
					int basePosition = br.Position;
					int instructionIndex = 0;
					try
					{
						BigEndianBinaryReader rdr = br.Section(code_length);
						while(!rdr.IsAtEnd)
						{
							instructions[instructionIndex].Read((ushort)(rdr.Position - basePosition), rdr, classFile);
							hasJsr |= instructions[instructionIndex].NormalizedOpCode == NormalizedByteCode.__jsr;
							instructionIndex++;
						}
						// we add an additional nop instruction to make it easier for consumers of the code array
						instructions[instructionIndex++].SetTermNop((ushort)(rdr.Position - basePosition));
					}
					catch(ClassFormatError x)
					{
						// any class format errors in the code block are actually verify errors
						verifyError = x.Message;
					}
					this.instructions = new Instruction[instructionIndex];
					Array.Copy(instructions, 0, this.instructions, 0, instructionIndex);
					// build the pcIndexMap
					int[] pcIndexMap = new int[this.instructions[instructionIndex - 1].PC + 1];
					for(int i = 0; i < pcIndexMap.Length; i++)
					{
						pcIndexMap[i] = -1;
					}
					for(int i = 0; i < instructionIndex - 1; i++)
					{
						pcIndexMap[this.instructions[i].PC] = i;
					}
					// convert branch offsets to indexes
					for(int i = 0; i < instructionIndex - 1; i++)
					{
						switch(this.instructions[i].NormalizedOpCode)
						{
							case NormalizedByteCode.__ifeq:
							case NormalizedByteCode.__ifne:
							case NormalizedByteCode.__iflt:
							case NormalizedByteCode.__ifge:
							case NormalizedByteCode.__ifgt:
							case NormalizedByteCode.__ifle:
							case NormalizedByteCode.__if_icmpeq:
							case NormalizedByteCode.__if_icmpne:
							case NormalizedByteCode.__if_icmplt:
							case NormalizedByteCode.__if_icmpge:
							case NormalizedByteCode.__if_icmpgt:
							case NormalizedByteCode.__if_icmple:
							case NormalizedByteCode.__if_acmpeq:
							case NormalizedByteCode.__if_acmpne:
							case NormalizedByteCode.__ifnull:
							case NormalizedByteCode.__ifnonnull:
							case NormalizedByteCode.__goto:
							case NormalizedByteCode.__jsr:
								this.instructions[i].SetTargetIndex(pcIndexMap[this.instructions[i].Arg1 + this.instructions[i].PC]);
								break;
							case NormalizedByteCode.__tableswitch:
							case NormalizedByteCode.__lookupswitch:
								this.instructions[i].MapSwitchTargets(pcIndexMap);
								break;
						}
					}
					// read exception table
					ushort exception_table_length = br.ReadUInt16();
					exception_table = new ExceptionTableEntry[exception_table_length];
					for(int i = 0; i < exception_table_length; i++)
					{
						ushort start_pc = br.ReadUInt16();
						ushort end_pc = br.ReadUInt16();
						ushort handler_pc = br.ReadUInt16();
						ushort catch_type = br.ReadUInt16();
						if(start_pc >= end_pc
							|| end_pc > code_length
							|| handler_pc >= code_length
							|| (catch_type != 0 && !classFile.SafeIsConstantPoolClass(catch_type)))
						{
							throw new ClassFormatError("Illegal exception table: {0}.{1}{2}", classFile.Name, method.Name, method.Signature);
						}
						classFile.MarkLinkRequiredConstantPoolItem(catch_type);
						// if start_pc, end_pc or handler_pc is invalid (i.e. doesn't point to the start of an instruction),
						// the index will be -1 and this will be handled by the verifier
						int startIndex = pcIndexMap[start_pc];
						int endIndex;
						if (end_pc == code_length)
						{
							// it is legal for end_pc to point to just after the last instruction,
							// but since there isn't an entry in our pcIndexMap for that, we have
							// a special case for this
							endIndex = instructionIndex - 1;
						}
						else
						{
							endIndex = pcIndexMap[end_pc];
						}
						int handlerIndex = pcIndexMap[handler_pc];
						exception_table[i] = new ExceptionTableEntry(startIndex, endIndex, handlerIndex, catch_type, i);
					}
					ushort attributes_count = br.ReadUInt16();
					for(int i = 0; i < attributes_count; i++)
					{
						switch(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()))
						{
							case "LineNumberTable":
								if((options & ClassFileParseOptions.LineNumberTable) != 0)
								{
									BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
									int count = rdr.ReadUInt16();
									lineNumberTable = new LineNumberTableEntry[count];
									for(int j = 0; j < count; j++)
									{
										lineNumberTable[j].start_pc = rdr.ReadUInt16();
										lineNumberTable[j].line_number = rdr.ReadUInt16();
										if(lineNumberTable[j].start_pc >= code_length)
										{
											throw new ClassFormatError("{0} (LineNumberTable has invalid pc)", classFile.Name);
										}
									}
									if(!rdr.IsAtEnd)
									{
										throw new ClassFormatError("{0} (LineNumberTable attribute has wrong length)", classFile.Name);
									}
								}
								else
								{
									br.Skip(br.ReadUInt32());
								}
								break;
							case "LocalVariableTable":
								if((options & ClassFileParseOptions.LocalVariableTable) != 0)
								{
									BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
									int count = rdr.ReadUInt16();
									localVariableTable = new LocalVariableTableEntry[count];
									for(int j = 0; j < count; j++)
									{
										localVariableTable[j].start_pc = rdr.ReadUInt16();
										localVariableTable[j].length = rdr.ReadUInt16();
										localVariableTable[j].name = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16());
										localVariableTable[j].descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()).Replace('/', '.');
										localVariableTable[j].index = rdr.ReadUInt16();
									}
									// NOTE we're intentionally not checking that we're at the end of the section
									// (optional attributes shouldn't cause ClassFormatError)
								}
								else
								{
									br.Skip(br.ReadUInt32());
								}
								break;
							default:
								br.Skip(br.ReadUInt32());
								break;
						}
					}
					// build the argmap
					string sig = method.Signature;
					List<int> args = new List<int>();
					int pos = 0;
					if(!method.IsStatic)
					{
						args.Add(pos++);
					}
					for(int i = 1; sig[i] != ')'; i++)
					{
						args.Add(pos++);
						switch(sig[i])
						{
							case 'L':
								i = sig.IndexOf(';', i);
								break;
							case 'D':
							case 'J':
								args.Add(-1);
								break;
							case '[':
							{
								while(sig[i] == '[')
								{
									i++;
								}
								if(sig[i] == 'L')
								{
									i = sig.IndexOf(';', i);
								}
								break;
							}
						}
					}
					argmap = args.ToArray();
					if(args.Count > max_locals)
					{
						throw new ClassFormatError("{0} (Arguments can't fit into locals)", classFile.Name);
					}
				}
Esempio n. 3
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");
					}
				}
			}
Esempio n. 4
0
			internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
				s = classFile.GetConstantPoolUtf8String(utf8_cp, string_index);
			}
Esempio n. 5
0
			internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
				ConstantPoolItemNameAndType name_and_type = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(name_and_type_index);
				// if the constant pool items referred to were strings, GetConstantPoolItem returns null
				if (name_and_type == null)
				{
					throw new ClassFormatError("Bad index in constant pool");
				}
				name = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.name_index));
				descriptor = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.descriptor_index).Replace('/', '.'));
			}
Esempio n. 6
0
			internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
				string descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, signature_index);
				if (descriptor == null || !IsValidMethodSig(descriptor))
				{
					throw new ClassFormatError("Invalid MethodType signature");
				}
				this.descriptor = String.Intern(descriptor.Replace('/', '.'));
			}
Esempio n. 7
0
			internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
				switch ((RefKind)ref_kind)
				{
					case RefKind.getField:
					case RefKind.getStatic:
					case RefKind.putField:
					case RefKind.putStatic:
						cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemFieldref;
						break;
					case RefKind.invokeSpecial:
					case RefKind.invokeVirtual:
					case RefKind.invokeStatic:
					case RefKind.newInvokeSpecial:
						cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemMethodref;
						break;
					case RefKind.invokeInterface:
						cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemInterfaceMethodref;
						break;
				}
				if (cpi == null)
				{
					throw new ClassFormatError("Invalid constant pool item MethodHandle");
				}
				if (ReferenceEquals(cpi.Name, StringConstants.INIT) && Kind != RefKind.newInvokeSpecial)
				{
					throw new ClassFormatError("Bad method name");
				}
			}
Esempio n. 8
0
			internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
				if(classFile.GetConstantPoolUtf8String(utf8_cp, name_index) == null
					|| classFile.GetConstantPoolUtf8String(utf8_cp, descriptor_index) == null)
				{
					throw new ClassFormatError("Illegal constant pool index");
				}
			}
Esempio n. 9
0
		internal ClassFile(byte[] buf, int offset, int length, string inputClassName, ClassFileParseOptions options)
		{
			try
			{
				BigEndianBinaryReader br = new BigEndianBinaryReader(buf, offset, length);
				if(br.ReadUInt32() != 0xCAFEBABE)
				{
					throw new ClassFormatError("{0} (Bad magic number)", inputClassName);
				}
				ushort minorVersion = br.ReadUInt16();
				ushort majorVersion = br.ReadUInt16();
				if((majorVersion & FLAG_MASK_MAJORVERSION) != majorVersion
					|| majorVersion < SupportedVersions.Minimum
					|| majorVersion > SupportedVersions.Maximum
					|| (majorVersion == SupportedVersions.Minimum && minorVersion < 3)
					|| (majorVersion == SupportedVersions.Maximum && minorVersion != 0))
				{
					throw new UnsupportedClassVersionError(inputClassName + " (" + majorVersion + "." + minorVersion + ")");
				}
				flags = majorVersion;
				int constantpoolcount = br.ReadUInt16();
				constantpool = new ConstantPoolItem[constantpoolcount];
				string[] utf8_cp = new string[constantpoolcount];
				for(int i = 1; i < constantpoolcount; i++)
				{
					Constant tag = (Constant)br.ReadByte();
					switch(tag)
					{
						case Constant.Class:
							constantpool[i] = new ConstantPoolItemClass(br);
							break;
						case Constant.Double:
							constantpool[i] = new ConstantPoolItemDouble(br);
							i++;
							break;
						case Constant.Fieldref:
							constantpool[i] = new ConstantPoolItemFieldref(br);
							break;
						case Constant.Float:
							constantpool[i] = new ConstantPoolItemFloat(br);
							break;
						case Constant.Integer:
							constantpool[i] = new ConstantPoolItemInteger(br);
							break;
						case Constant.InterfaceMethodref:
							constantpool[i] = new ConstantPoolItemInterfaceMethodref(br);
							break;
						case Constant.Long:
							constantpool[i] = new ConstantPoolItemLong(br);
							i++;
							break;
						case Constant.Methodref:
							constantpool[i] = new ConstantPoolItemMethodref(br);
							break;
						case Constant.NameAndType:
							constantpool[i] = new ConstantPoolItemNameAndType(br);
							break;
						case Constant.MethodHandle:
							if (majorVersion < 51)
								goto default;
							constantpool[i] = new ConstantPoolItemMethodHandle(br);
							break;
						case Constant.MethodType:
							if (majorVersion < 51)
								goto default;
							constantpool[i] = new ConstantPoolItemMethodType(br);
							break;
						case Constant.InvokeDynamic:
							if (majorVersion < 51)
								goto default;
							constantpool[i] = new ConstantPoolItemInvokeDynamic(br);
							break;
						case Constant.String:
							constantpool[i] = new ConstantPoolItemString(br);
							break;
						case Constant.Utf8:
							utf8_cp[i] = br.ReadString(inputClassName);
							break;
						default:
							throw new ClassFormatError("{0} (Illegal constant pool type 0x{1:X})", inputClassName, tag);
					}
				}
				for(int i = 1; i < constantpoolcount; i++)
				{
					if(constantpool[i] != null)
					{
						try
						{
							constantpool[i].Resolve(this, utf8_cp, options);
						}
						catch(ClassFormatError x)
						{
							// HACK at this point we don't yet have the class name, so any exceptions throw
							// are missing the class name
							throw new ClassFormatError("{0} ({1})", inputClassName, x.Message);
						}
						catch(IndexOutOfRangeException)
						{
							throw new ClassFormatError("{0} (Invalid constant pool item #{1})", inputClassName, i);
						}
						catch(InvalidCastException)
						{
							throw new ClassFormatError("{0} (Invalid constant pool item #{1})", inputClassName, i);
						}
					}
				}
				access_flags = (Modifiers)br.ReadUInt16();
				// NOTE although the vmspec says (in 4.1) that interfaces must be marked abstract, earlier versions of
				// javac (JDK 1.1) didn't do this, so the VM doesn't enforce this rule for older class files.
				// NOTE although the vmspec implies (in 4.1) that ACC_SUPER is illegal on interfaces, it doesn't enforce this
				// for older class files.
				// (See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6320322)
				if((IsInterface && IsFinal)
					|| (IsAbstract && IsFinal)
					|| (majorVersion >= 49 && IsAnnotation && !IsInterface)
					|| (majorVersion >= 49 && IsInterface && (!IsAbstract || IsSuper || IsEnum)))
				{
					throw new ClassFormatError("{0} (Illegal class modifiers 0x{1:X})", inputClassName, access_flags);
				}
				this_class = br.ReadUInt16();
				ValidateConstantPoolItemClass(inputClassName, this_class);
				super_class = br.ReadUInt16();
				ValidateConstantPoolItemClass(inputClassName, super_class);
				if(IsInterface && (super_class == 0 || this.SuperClass != "java.lang.Object"))
				{
					throw new ClassFormatError("{0} (Interfaces must have java.lang.Object as superclass)", Name);
				}
				// most checks are already done by ConstantPoolItemClass.Resolve, but since it allows
				// array types, we do need to check for that
				if(this.Name[0] == '[')
				{
					throw new ClassFormatError("Bad name");
				}
				int interfaces_count = br.ReadUInt16();
				interfaces = new ConstantPoolItemClass[interfaces_count];
				for(int i = 0; i < interfaces.Length; i++)
				{
					int index = br.ReadUInt16();
					if(index == 0 || index >= constantpool.Length)
					{
						throw new ClassFormatError("{0} (Illegal constant pool index)", Name);
					}
					ConstantPoolItemClass cpi = constantpool[index] as ConstantPoolItemClass;
					if(cpi == null)
					{
						throw new ClassFormatError("{0} (Interface name has bad constant type)", Name);
					}
					interfaces[i] = cpi;
					for(int j = 0; j < i; j++)
					{
						if(ReferenceEquals(interfaces[j].Name, cpi.Name))
						{
							throw new ClassFormatError("{0} (Repetitive interface name)", Name);
						}
					}
				}
				int fields_count = br.ReadUInt16();
				fields = new Field[fields_count];
				for(int i = 0; i < fields_count; i++)
				{
					fields[i] = new Field(this, utf8_cp, br);
					string name = fields[i].Name;
					if(!IsValidFieldName(name, majorVersion))
					{
						throw new ClassFormatError("{0} (Illegal field name \"{1}\")", Name, name);
					}
					for(int j = 0; j < i; j++)
					{
						if(ReferenceEquals(fields[j].Name, name) && ReferenceEquals(fields[j].Signature, fields[i].Signature))
						{
							throw new ClassFormatError("{0} (Repetitive field name/signature)", Name);
						}
					}
				}
				int methods_count = br.ReadUInt16();
				methods = new Method[methods_count];
				for(int i = 0; i < methods_count; i++)
				{
					methods[i] = new Method(this, utf8_cp, options, br);
					string name = methods[i].Name;
					string sig = methods[i].Signature;
					if(!IsValidMethodName(name, majorVersion))
					{
						if(!ReferenceEquals(name, StringConstants.INIT) && !ReferenceEquals(name, StringConstants.CLINIT))
						{
							throw new ClassFormatError("{0} (Illegal method name \"{1}\")", Name, name);
						}
						if(!sig.EndsWith("V"))
						{
							throw new ClassFormatError("{0} (Method \"{1}\" has illegal signature \"{2}\")", Name, name, sig);
						}
					}
					for(int j = 0; j < i; j++)
					{
						if(ReferenceEquals(methods[j].Name, name) && ReferenceEquals(methods[j].Signature, sig))
						{
							throw new ClassFormatError("{0} (Repetitive method name/signature)", Name);
						}
					}
				}
				int attributes_count = br.ReadUInt16();
				for(int i = 0; i < attributes_count; i++)
				{
					switch(GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()))
					{
						case "Deprecated":
							if(br.ReadUInt32() != 0)
							{
								throw new ClassFormatError("Invalid Deprecated attribute length");
							}
							flags |= FLAG_MASK_DEPRECATED;
							break;
						case "SourceFile":
							if(br.ReadUInt32() != 2)
							{
								throw new ClassFormatError("SourceFile attribute has incorrect length");
							}
							sourceFile = GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16());
							break;
						case "InnerClasses":
						{
							BigEndianBinaryReader rdr = br;
							uint attribute_length = br.ReadUInt32();
							ushort count = rdr.ReadUInt16();
							if(this.MajorVersion >= 49 && attribute_length != 2 + count * (2 + 2 + 2 + 2))
							{
								throw new ClassFormatError("{0} (InnerClasses attribute has incorrect length)", this.Name);
							}
							innerClasses = new InnerClass[count];
							for(int j = 0; j < innerClasses.Length; j++)
							{
								innerClasses[j].innerClass = rdr.ReadUInt16();
								innerClasses[j].outerClass = rdr.ReadUInt16();
								innerClasses[j].name = rdr.ReadUInt16();
								innerClasses[j].accessFlags = (Modifiers)rdr.ReadUInt16();
								if(innerClasses[j].innerClass != 0 && !(GetConstantPoolItem(innerClasses[j].innerClass) is ConstantPoolItemClass))
								{
									throw new ClassFormatError("{0} (inner_class_info_index has bad constant pool index)", this.Name);
								}
								if(innerClasses[j].outerClass != 0 && !(GetConstantPoolItem(innerClasses[j].outerClass) is ConstantPoolItemClass))
								{
									throw new ClassFormatError("{0} (outer_class_info_index has bad constant pool index)", this.Name);
								}
								if(innerClasses[j].name != 0 && utf8_cp[innerClasses[j].name] == null)
								{
									throw new ClassFormatError("{0} (inner class name has bad constant pool index)", this.Name);
								}
								if(innerClasses[j].innerClass == innerClasses[j].outerClass)
								{
									throw new ClassFormatError("{0} (Class is both inner and outer class)", this.Name);
								}
								if(innerClasses[j].innerClass != 0 && innerClasses[j].outerClass != 0)
								{
									MarkLinkRequiredConstantPoolItem(innerClasses[j].innerClass);
									MarkLinkRequiredConstantPoolItem(innerClasses[j].outerClass);
								}
							}
							break;
						}
						case "Signature":
							if(majorVersion < 49)
							{
								goto default;
							}
							if(br.ReadUInt32() != 2)
							{
								throw new ClassFormatError("Signature attribute has incorrect length");
							}
							signature = GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16());
							break;
						case "EnclosingMethod":
							if(majorVersion < 49)
							{
								goto default;
							}
							if(br.ReadUInt32() != 4)
							{
								throw new ClassFormatError("EnclosingMethod attribute has incorrect length");
							}
							else
							{
								int class_index = br.ReadUInt16();
								int method_index = br.ReadUInt16();
								if(method_index == 0)
								{
									enclosingMethod = new string[] {
										GetConstantPoolClass(class_index),
										null,
										null
																   };
								}
								else
								{
									ConstantPoolItemNameAndType m = (ConstantPoolItemNameAndType)GetConstantPoolItem(method_index);
									enclosingMethod = new string[] {
										GetConstantPoolClass(class_index),
										GetConstantPoolUtf8String(utf8_cp, m.name_index),
										GetConstantPoolUtf8String(utf8_cp, m.descriptor_index).Replace('/', '.')
																   };
								}
							}
							break;
						case "RuntimeVisibleAnnotations":
							if(majorVersion < 49)
							{
								goto default;
							}
							annotations = ReadAnnotations(br, this, utf8_cp);
							break;
#if STATIC_COMPILER
						case "RuntimeInvisibleAnnotations":
							if(majorVersion < 49)
							{
								goto default;
							}
							foreach(object[] annot in ReadAnnotations(br, this, utf8_cp))
							{
								if(annot[1].Equals("Likvm/lang/Internal;"))
								{
									this.access_flags &= ~Modifiers.AccessMask;
									flags |= FLAG_MASK_INTERNAL;
								}
							}
							break;
#endif
						case "BootstrapMethods":
							if(majorVersion < 51)
							{
								goto default;
							}
							bootstrapMethods = ReadBootstrapMethods(br, this);
							break;
						case "IKVM.NET.Assembly":
							if(br.ReadUInt32() != 2)
							{
								throw new ClassFormatError("IKVM.NET.Assembly attribute has incorrect length");
							}
							ikvmAssembly = GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16());
							break;
						default:
							br.Skip(br.ReadUInt32());
							break;
					}
				}
				// validate the invokedynamic entries to point into the bootstrapMethods array
				for(int i = 1; i < constantpoolcount; i++)
				{
					ConstantPoolItemInvokeDynamic cpi;
					if(constantpool[i] != null
						&& (cpi = constantpool[i] as ConstantPoolItemInvokeDynamic) != null)
					{
						if(bootstrapMethods == null || cpi.BootstrapMethod >= bootstrapMethods.Length)
						{
							throw new ClassFormatError("Short length on BootstrapMethods in class file");
						}
					}
				}
				if(br.Position != offset + length)
				{
					throw new ClassFormatError("Extra bytes at the end of the class file");
				}
			}
			catch(OverflowException)
			{
				throw new ClassFormatError("Truncated class file (or section)");
			}
			catch(IndexOutOfRangeException)
			{
				// TODO we should throw more specific errors
				throw new ClassFormatError("Unspecified class file format error");
			}
			//		catch(Exception x)
			//		{
			//			Console.WriteLine(x);
			//			FileStream fs = File.Create(inputClassName + ".broken");
			//			fs.Write(buf, offset, length);
			//			fs.Close();
			//			throw;
			//		}
		}
Esempio n. 10
0
			internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
				name = classFile.GetConstantPoolUtf8String(utf8_cp, name_index);
				if(name.Length > 0)
				{
					// We don't enforce the strict class name rules in the static compiler, since HotSpot doesn't enforce *any* rules on
					// class names for the system (and boot) class loader. We still need to enforce the 1.5 restrictions, because we
					// rely on those invariants.
#if !STATIC_COMPILER
					if(classFile.MajorVersion < 49 && (options & ClassFileParseOptions.RelaxedClassNameValidation) == 0)
					{
						char prev = name[0];
						if(Char.IsLetter(prev) || prev == '$' || prev == '_' || prev == '[' || prev == '/')
						{
							int skip = 1;
							int end = name.Length;
							if(prev == '[')
							{
								if(!IsValidFieldSig(name))
								{
									goto barf;
								}
								while(name[skip] == '[')
								{
									skip++;
								}
								if(name.EndsWith(";"))
								{
									end--;
								}
							}
							for(int i = skip; i < end; i++)
							{
								char c = name[i];
								if(!Char.IsLetterOrDigit(c) && c != '$' && c != '_' && (c != '/' || prev == '/'))
								{
									goto barf;
								}
								prev = c;
							}
							name = String.Intern(name.Replace('/', '.'));
							return;
						}
					}
					else
#endif
					{
						// since 1.5 the restrictions on class names have been greatly reduced
						int end = name.Length;
						if(name[0] == '[')
						{
							if(!IsValidFieldSig(name))
							{
								goto barf;
							}
							// the semicolon is only allowed at the end and IsValidFieldSig enforces this,
							// but since invalidJava15Characters contains the semicolon, we decrement end
							// to make the following check against invalidJava15Characters ignore the
							// trailing semicolon.
							if(name[end - 1] == ';')
							{
								end--;
							}
						}
						if(name.IndexOfAny(invalidJava15Characters, 0, end) >= 0)
						{
							goto barf;
						}
						name = String.Intern(name.Replace('/', '.'));
						return;
					}
				}
				barf:
					throw new ClassFormatError("Invalid class name \"{0}\"", name);
			}
Esempio n. 11
0
			internal virtual void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options)
			{
			}