Пример #1
0
 public void SetLocalInAllFrames(int index, JavaType type, JavaException.Where Where)
 {
     SetLocalInOneFrame(top, index, type, Where);
     foreach (var kvp in frames)
     {
         SetLocalInOneFrame(kvp.Value, index, type, Where);
     }
Пример #2
0
 public JavaType(string descriptor, JavaException.Where Where)
 {
     if (ParseType(descriptor, 0) != descriptor.Length)
     {
         throw Where.Exception($"bad field descriptor {descriptor}");
     }
 }
Пример #3
0
        public int Put(JavaConstant newConst, JavaException.Where Where)
        {
            var newConstType = newConst.GetType();
            int n            = pool.Count;

            for (int i = 1; i < n; i++)
            {
                var oldConst = pool[i];
                if (oldConst?.GetType() == newConstType && oldConst.Equals(newConst))
                {
                    return((ushort)i);
                }
            }

            if (!editable)
            {
                throw Where.Exception("new constants not allowed");
            }
            pool.Add(newConst);

            if (newConst is JavaConstant.Long || newConst is JavaConstant.Double)
            {
                pool.Add(null);     // section 4.4.5
            }
            return(n);
        }
Пример #4
0
 public bool LoadFrame(ushort offsetLabel, bool keepStack,
                       JavaException.Where Where)
 {
     if (frames.TryGetValue(offsetLabel, out var frame))
     {
         top.locals = new List <JavaType>(frame.locals);
         if (keepStack)
         {
             top.stack = new List <JavaType>(frame.stack);
             curStack  = 0;
             foreach (var e in top.stack)
             {
                 curStack += e.Category;
             }
         }
         else
         {
             top.stack.Clear();
         }
         return(true);
     }
     else if (Where != null)
     {
         throw Where.Exception($"missing stack map at offset {offsetLabel:X4}");
     }
     return(false);
 }
Пример #5
0
 public int GetMaxStackSize(JavaException.Where Where)
 {
     if (top.stack.Count != 0)
     {
         throw Where.Exception($"operand stack is not empty: [ {string.Join(", ", top.stack)} ]");
     }
     return(maxStack);
 }
Пример #6
0
 public T Get <T>(int index, JavaException.Where Where)
 {
     if (index > 0 && index < pool.Count &&
         pool[index] is T o && o != null)
     {
         return(o);
     }
     throw Where.Exception($"expected constant of type '{typeof(T).Name}' at index {index}");
 }
Пример #7
0
        public JavaType PopStack(JavaException.Where Where)
        {
            int n = top.stack.Count - 1;

            if (n < 0)
            {
                throw Where.Exception("underflow in operand stack");
            }
            var retval = top.stack[n];

            curStack -= retval.Category;
            top.stack.RemoveAt(n);
            return(retval);
        }
Пример #8
0
        public int[] SaveFrame(ushort offsetLabel, bool branchTarget,
                               JavaException.Where Where)
        {
            #if false
            {
                Console.WriteLine("-----------> Save Frame at " + offsetLabel.ToString("X4") + " branchTarget " + branchTarget);
                var(old1, old2) = FrameToString(offsetLabel);
                var(top1, top2) = FrameToString();
                Console.WriteLine("old frame = " + old1 + " ; " + old2);
                Console.WriteLine("top frame = " + top1 + " ; " + top2);
                Console.WriteLine(new System.Diagnostics.StackTrace(true).ToString());
                Console.WriteLine("<--------------");
            }
            #endif

            List <JavaType> copyLocals  = null;
            List <JavaType> copyStack   = null;
            int[]           resetLocals = null;

            if (frames.TryGetValue(offsetLabel, out var old))
            {
                if (branchTarget)
                {
                    // we are saving a frame that is the target of a branch,
                    // so merging should not affect the current stack frame.
                    copyLocals = new List <JavaType>(top.locals);
                    copyStack  = new List <JavaType>(top.stack);
                }

                resetLocals = MergeFrame(old, offsetLabel, Where);

                if (branchTarget)
                {
                    old.branchTarget = true;
                }
            }
            else
            {
                top.branchTarget = branchTarget;
                frames.Add(offsetLabel, top);
            }

            var newTop = new Frame();
            newTop.locals = copyLocals ?? new List <JavaType>(top.locals);
            newTop.stack  = copyStack ?? new List <JavaType>(top.stack);
            top           = newTop;

            return(resetLocals);
        }
Пример #9
0
        public static string Decode(byte[] blk, JavaException.Where Where)
        {
            int n  = blk.Length;
            var ch = new char[n];
            int i  = 0;
            int j  = 0;

            while (i < n)
            {
                byte b0 = blk[i++];
                if ((b0 & 0x80) == 0)
                {
                    // one-byte sequence
                    ch[j++] = (char)b0;
                    continue;
                }
                if (i < n)
                {
                    byte b1 = blk[i++];
                    if ((b1 & 0xC0) == 0x80)
                    {
                        if ((b0 & 0xE0) == 0xC0)
                        {
                            // two-byte sequence
                            ch[j++] = (char)(((b0 & 0x1F) << 6) + (b1 & 0x3F));
                            continue;
                        }
                        else if (i < n && (b0 & 0xF0) == 0xE0)
                        {
                            byte b2 = blk[i++];
                            if ((b1 & 0xC0) == 0x80)
                            {
                                // three-byte sequence
                                ch[j++] = (char)
                                          (((b0 & 0x0F) << 12) + ((b1 & 0x3F) << 6) + (b2 & 0x3F));
                                continue;
                            }
                        }
                    }
                }
                throw Where.Exception("invalid UTF-8 data (at offset " + i + " in data)");
            }

            return(new string(ch, 0, j));
        }
Пример #10
0
        public JavaMethodType(string descriptor, JavaException.Where Where)
        {
            if (descriptor[0] == '(')
            {
                var list = new List <JavaFieldRef>();

                var index = 1;
                while (index < descriptor.Length)
                {
                    if (descriptor[index] == ')')
                    {
                        break;
                    }
                    var nextType = new JavaType();
                    if ((index = nextType.ParseType(descriptor, index)) == -1)
                    {
                        break;
                    }
                    else
                    {
                        list.Add(new JavaFieldRef(null, nextType));
                    }
                }

                if (index > 0 && index + 1 < descriptor.Length)
                {
                    Parameters = list;
                    ReturnType = new JavaType();

                    if (descriptor[++index] == 'V')
                    {
                        return;
                    }

                    if (ReturnType.ParseType(descriptor, index) == descriptor.Length)
                    {
                        return;
                    }
                }
            }

            throw Where.Exception($"bad method descriptor '{descriptor}'");
        }
Пример #11
0
 static void SetLocalInOneFrame(Frame frm, int index, JavaType type,
                                JavaException.Where Where)
 {
     if (index < frm.locals.Count)
     {
         if (!frm.locals[index].Equals(type))
         {
             if (Where != null && frm.locals[index] != Top)
             {
                 throw Where.Exception($"local already assigned in stack frame");
             }
             frm.locals[index] = type;
         }
     }
     else
     {
         while (index > frm.locals.Count)
         {
             frm.locals.Add(Top);
         }
         frm.locals.Add(type);
     }
 }
Пример #12
0
        JavaWriter(Stream _stream, JavaClass _class)
        {
            Where = new JavaException.Where();

            var memoryStream = new MemoryStream();

            stream        = memoryStream;
            forkedStreams = new Stack <Stream>();

            constants = new JavaConstantPool();

            _class.Write(this);

            stream = _stream;

            Write32(0xCAFEBABE);
            Write16(0);
            Write16(52);

            constants.Write(this);
            memoryStream.WriteTo(_stream);
            memoryStream.Dispose();
        }
Пример #13
0
        JavaReader(Stream _stream, string whereText, bool withCode)
        {
            Where = new JavaException.Where();
            Where.Push(whereText);

            stream = _stream;

            if (Read32() != 0xCAFEBABE)
            {
                throw Where.Exception("bad class magic number");
            }

            var(minorVersion, majorVersion) = (Read16(), Read16());
            if (majorVersion < 45)
            {
                throw Where.Exception("bad class major version number");
            }

            constants = new JavaConstantPool(this);

            new JavaClass(this, majorVersion, minorVersion, withCode);

            Where.Pop();
        }
Пример #14
0
        public void InitConstant(object value, JavaException.Where Where)
        {
            bool ok = false;

            if (Type.ArrayRank == 0 && (Flags & JavaAccessFlags.ACC_STATIC) != 0)
            {
                if ((Type.ClassName == "java.lang.String" && value is string) ||
                    (Type.PrimitiveType == TypeCode.Double && value is double) ||
                    (Type.PrimitiveType == TypeCode.Single && value is float) ||
                    (Type.PrimitiveType == TypeCode.Int64 && value is long))
                {
                    ok = true;
                }
                else if (Type.PrimitiveType == TypeCode.UInt64 && value is ulong)
                {
                    value = (long)((ulong)value);
                    ok    = true;
                }
                else
                {
                    switch (value)
                    {
                    case bool boolValue:      value = (int)(boolValue ? 1 : 0);  break;

                    case byte byteValue:      value = (int)byteValue;            break;

                    case sbyte sbyteValue:    value = (int)sbyteValue;           break;

                    case char charValue:      value = (int)charValue;            break;

                    case short shortValue:    value = (int)shortValue;           break;

                    case ushort ushortValue:  value = (int)ushortValue;          break;

                    case uint uintValue:      value = (int)uintValue;            break;
                    }

                    if (value is int)
                    {
                        if (Type.PrimitiveType == TypeCode.Boolean ||
                            Type.PrimitiveType == TypeCode.Byte ||
                            Type.PrimitiveType == TypeCode.SByte ||
                            Type.PrimitiveType == TypeCode.Char ||
                            Type.PrimitiveType == TypeCode.Int16 ||
                            Type.PrimitiveType == TypeCode.UInt16 ||
                            Type.PrimitiveType == TypeCode.Int32 ||
                            Type.PrimitiveType == TypeCode.UInt32)
                        {
                            ok = true;
                        }
                    }
                }
            }
            if (ok)
            {
                Constant = value;
            }
            else
            {
                throw Where.Exception($"bad constant value or non-static field of type '{Type}'");
            }
        }
Пример #15
0
 public JavaFieldRef(string name, string descriptor, JavaException.Where Where)
 {
     Name = name;
     Type = new JavaType(descriptor, Where);
 }
Пример #16
0
 public JavaMethodRef(string descriptor, JavaException.Where Where)
     : base(descriptor, Where)
 {
 }
Пример #17
0
        int[] MergeFrame(Frame old, ushort offsetLabel, JavaException.Where Where)
        {
            //
            // compare locals, with the exception that a 'top' type (in the
            // sense of an uninitialized local), which was already recorded
            // in one frame, may override a non-'top' type in the other
            // frame.  this is the result of branching over
            //
            // ifnonnull L1     local 7 is uninitialized/'top' here
            // aload_1          assume local 1 is float
            // astore_7         local 7 is now initialized as float
            // L1: ...          conflicting frames, and we keep 'top'
            //
            // note:  if either frame contains more locals than the other
            // frame, we treat the missing locals as if they were defined
            // as a 'top' type (i.e. uninitialized) in the other frame.
            //

            List <int> resetLocals = null;

            var topLocals = top.locals;
            var oldLocals = old.locals;

            int  topLocalsCount = topLocals.Count;
            int  oldLocalsCount = oldLocals.Count;
            bool same           = true;

            int iTop = 0;
            int iOld = 0;

            while (iTop < topLocalsCount || iOld < oldLocalsCount)
            {
                var oldElem = (iOld < oldLocalsCount) ? oldLocals[iOld] : Top;
                var topElem = (iTop < topLocalsCount) ? topLocals[iTop] : Top;

                if (!topElem.Equals(oldElem))
                {
                    if (oldElem.Equals(Top))
                    {
                        topLocals[iTop] = topElem = Top;
                    }
                    else if (topElem.Equals(Top))
                    {
                        oldLocals[iOld] = oldElem = Top;
                        // report locals that were reset during merge
                        if (resetLocals == null)
                        {
                            resetLocals = new List <int>();
                        }
                        resetLocals.Add(iOld);
                    }

                    else if (!topElem.AssignableTo(oldElem))
                    {
                        same = false;
                        break;
                    }
                }

                iTop += topElem.Category;
                iOld += oldElem.Category;
            }

            //
            // compare stacks, with the exception that a 'null' type, which
            // appears in one frame, may be overridden by a more specific
            // class type from the other frame, e.g.
            //
            // ifnonnull L1     stack is empty
            // aconst_null      stack is [ null ]
            // goto L2
            // L1.  aload_1     if local 1 is string, stack is [ string ]
            // L2.  ...         conflicting frames, and we keep [ string ]
            //
            // note that the result would be the same even if 'aconst_null'
            // and 'aload_1'.  and also note that 'uninitializedThis' is
            // treated in the same way as 'null'.
            //
            // a second exception is for assignability through the virtual
            // call to JavaType.AssignableTo.  if an element from a stack is
            // assignable to the othe stack, then the other stack overrides.
            // for example, any reference can be assigned to java.lang.Object,
            // so a conflict is resolved by overriding with java.lang.Object.
            //

            var topStack = top.stack;
            var oldStack = old.stack;

            int numStack = topStack.Count;

            same &= (numStack == oldStack.Count);

            if (same)
            {
                for (int i = 0; i < numStack; i++)
                {
                    var oldElem = oldStack[i];
                    var topElem = topStack[i];

                    if (!topElem.Equals(oldElem))
                    {
                        if (oldElem.Equals(Null) || oldElem.Equals(UninitializedThis))
                        {
                            oldStack[i] = topElem;
                        }

                        else if (topElem.Equals(Null) || topElem.Equals(UninitializedThis))
                        {
                            topStack[i] = oldElem;
                        }

                        else if (oldElem.AssignableTo(topElem))
                        {
                            oldStack[i] = topElem;
                        }

                        else if (topElem.AssignableTo(oldElem))
                        {
                            topStack[i] = oldElem;
                        }

                        else if (old.branchTarget &&
                                 (topElem = oldElem.ResolveConflict(topElem)) != null)
                        {
                            // the ternary operator ?: may produce code that causes a conflict:
                            //      object x = flag ? (object) new A() : (object) new B();
                            // if we detect such a conflict at a branch target, we assume this
                            // is the cause, and set the stack elements to java.lang.Object
                            oldStack[i] = topStack[i] = topElem;
                        }

                        else
                        {
                            same = false;
                            break;
                        }
                    }
                }
            }

            if (!same)
            {
                #if DEBUGDIAG
                var(old1, old2) = FrameToString(offsetLabel);
                var(top1, top2) = FrameToString();
                Console.WriteLine("old frame = " + old1 + " ; " + old2);
                Console.WriteLine("top frame = " + top1 + " ; " + top2);
                #endif
                throw Where.Exception($"conflicting stack frames at offset {offsetLabel:X4}");
            }

            return((resetLocals != null) ? resetLocals.ToArray() : null);
        }