]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libgcj/16032 (libgcj should reject class files with incorrect version numbers)
authorTom Tromey <tromey@redhat.com>
Thu, 15 Sep 2005 22:02:13 +0000 (22:02 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Thu, 15 Sep 2005 22:02:13 +0000 (22:02 +0000)
PR libgcj/16032:
* interpret.cc (AVAL1U): Resolve pool entry when not direct
threaded.
(AVAL2U): Likewise.
(compile): Handle 'ldc class' specially.
(_Jv_InterpMethod::run): Added special 'ldc class' instruction.
* verify.cc (check_constant): Handle 'ldc class' for 1.5 classes.
* defineclass.cc (handleCodeAttribute): Set new field.
(MAJOR_1_1, MINOR_1_1, MAJOR_1_2, MINOR_1_2, MAJOR_1_3, MINOR_1_3,
MAJOR_1_4, MINOR_1_4, MAJOR_1_5, MINOR_1_5): New defines.
(parse): Check version numbers.
(_Jv_ClassReader::is_15): New field.
(_Jv_ClassReader): Initialize it.
* include/java-interp.h (_Jv_InterpMethod::is_15): New field.

From-SVN: r104325

libjava/ChangeLog
libjava/defineclass.cc
libjava/include/java-interp.h
libjava/interpret.cc
libjava/verify.cc

index ad81598dee9dab66824483ff29d136c6e01e5d2d..3520d8c3c0812aec1b32ebd7285bb065bf4e3319 100644 (file)
@@ -1,3 +1,20 @@
+2005-09-15  Tom Tromey  <tromey@redhat.com>
+
+       PR libgcj/16032:
+       * interpret.cc (AVAL1U): Resolve pool entry when not direct
+       threaded.
+       (AVAL2U): Likewise.
+       (compile): Handle 'ldc class' specially.
+       (_Jv_InterpMethod::run): Added special 'ldc class' instruction.
+       * verify.cc (check_constant): Handle 'ldc class' for 1.5 classes.
+       * defineclass.cc (handleCodeAttribute): Set new field.
+       (MAJOR_1_1, MINOR_1_1, MAJOR_1_2, MINOR_1_2, MAJOR_1_3, MINOR_1_3,
+       MAJOR_1_4, MINOR_1_4, MAJOR_1_5, MINOR_1_5): New defines.
+       (parse): Check version numbers.
+       (_Jv_ClassReader::is_15): New field.
+       (_Jv_ClassReader): Initialize it.
+       * include/java-interp.h (_Jv_InterpMethod::is_15): New field.
+
 2005-09-15  Tom Tromey  <tromey@redhat.com>
 
        For PR libgcj/23288:
index d12e32784817d8d9d55e8a2512057c0582d5ec64..89e0636f4aa71d88607ff44e078b0723dce11e39 100644 (file)
@@ -101,13 +101,17 @@ struct _Jv_ClassReader
 
   // the class to define (see java-interp.h)
   jclass          def;
-  
+
   // the classes associated interpreter data.
   _Jv_InterpClass  *def_interp;
 
   // The name we found.
   _Jv_Utf8Const **found_name;
 
+  // True if this is a 1.5 class file.
+  bool             is_15;
+
+
   /* check that the given number of input bytes are available */
   inline void check (int num)
   {
@@ -233,6 +237,8 @@ struct _Jv_ClassReader
     bytes  = (unsigned char*) (elements (data)+offset);
     len    = length;
     pos    = 0;
+    is_15  = false;
+
     def    = klass;
     found_name = name_result;
 
@@ -302,19 +308,32 @@ _Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length,
 \f
 /** This section defines the parsing/scanning of the class data */
 
+// Major and minor version numbers for various releases.
+#define MAJOR_1_1 45
+#define MINOR_1_1  3
+#define MAJOR_1_2 46
+#define MINOR_1_2  0
+#define MAJOR_1_3 47
+#define MINOR_1_3  0
+#define MAJOR_1_4 48
+#define MINOR_1_4  0
+#define MAJOR_1_5 49
+#define MINOR_1_5  0
+
 void
 _Jv_ClassReader::parse ()
 {
   int magic = read4 ();
-
-  /* FIXME: Decide which range of version numbers to allow */
-
-  /* int minor_version = */ read2u ();
-  /* int major_verson  = */ read2u ();
-
   if (magic != (int) 0xCAFEBABE)
     throw_class_format_error ("bad magic number");
 
+  int minor_version = read2u ();
+  int major_version = read2u ();
+  if (major_version < MAJOR_1_1 || major_version > MAJOR_1_5
+      || (major_version == MAJOR_1_5 && minor_version > MINOR_1_5))
+    throw_class_format_error ("unrecognized class file version");
+  is_15 = (major_version == MAJOR_1_5);
+
   pool_count = read2u ();
 
   read_constpool ();
@@ -1318,6 +1337,7 @@ void _Jv_ClassReader::handleCodeAttribute
   method->max_locals     = max_locals;
   method->code_length    = code_length;
   method->exc_count      = exc_table_length;
+  method->is_15          = is_15;
   method->defining_class = def;
   method->self           = &def->methods[method_index];
   method->prepared       = NULL;
index 5155557c769b5173f9994808c06a29c9dcc9454b..269e39c5a5ef71bfe6f2d52c7038889fc4055a95 100644 (file)
@@ -137,6 +137,7 @@ class _Jv_InterpMethod : public _Jv_MethodBase
   int              code_length;
 
   _Jv_ushort       exc_count;
+  bool             is_15;
 
   // Length of the line_table - when this is zero then line_table is NULL.
   int line_table_len;  
@@ -218,7 +219,8 @@ _Jv_GetFirstMethod (_Jv_InterpClass *klass)
   return klass->interpreted_methods;
 }
 
-struct _Jv_ResolvedMethod {
+struct _Jv_ResolvedMethod
+{
   jint            stack_item_count;    
   jint            vtable_index;        
   jclass          klass;
index dcda95e64de71a9c3921e22d11f5ded63830dc4b..dacf19dfb12e1da403c1d71a0c0a5c9243255f1f 100644 (file)
@@ -507,7 +507,16 @@ _Jv_InterpMethod::compile (const void * const *insn_targets)
              {
                int index = get1u (pc);
                ++pc;
-               SET_DATUM (pool_data[index].o);
+               // For an unresolved class we want to delay resolution
+               // until execution.
+               if (defining_class->constants.tags[index] == JV_CONSTANT_Class)
+                 {
+                   --next;
+                   SET_INSN (insn_targets[int (op_jsr_w) + 1]);
+                   SET_INT (index);
+                 }
+               else
+                 SET_DATUM (pool_data[index].o);
              }
              break;
 
@@ -537,7 +546,16 @@ _Jv_InterpMethod::compile (const void * const *insn_targets)
              {
                int index = get2u (pc);
                pc += 2;
-               SET_DATUM (pool_data[index].o);
+               // For an unresolved class we want to delay resolution
+               // until execution.
+               if (defining_class->constants.tags[index] == JV_CONSTANT_Class)
+                 {
+                   --next;
+                   SET_INSN (insn_targets[int (op_jsr_w) + 1]);
+                   SET_INT (index);
+                 }
+               else
+                 SET_DATUM (pool_data[index].o);
              }
              break;
 
@@ -1017,7 +1035,11 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
     INSN_LABEL(ifnonnull),
     INSN_LABEL(goto_w),
     INSN_LABEL(jsr_w),
+#ifdef DIRECT_THREADED
+    INSN_LABEL (ldc_class)
+#else
     0
+#endif
   };
 
   pc_t pc;
@@ -1058,8 +1080,16 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
 #define GET2S() (pc += 2, get2s (pc- 2))
 #define GET1U() get1u (pc++)
 #define GET2U() (pc += 2, get2u (pc - 2))
-#define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
-#define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
+  // Note that these could be more efficient when not handling 'ldc
+  // class'.
+#define AVAL1U()                                               \
+  ({ int index = get1u (pc++);                                 \
+      resolve_pool_entry (meth->defining_class, index).o; })
+#define AVAL2U()                                               \
+  ({ int index = get2u (pc); pc += 2;                          \
+      resolve_pool_entry (meth->defining_class, index).o; })
+  // Note that we don't need to resolve the pool entry here as class
+  // constants are never wide.
 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
 #define SKIP_GOTO pc += 2
 #define GOTO_VAL() pc - 1 + get2s (pc)
@@ -1320,6 +1350,19 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
       PUSHA ((jobject) AVAL2U ());
       NEXT_INSN;
 
+#ifdef DIRECT_THREADED
+      // For direct threaded we have a separate 'ldc class' operation.
+    insn_ldc_class:
+      {
+       // We could rewrite the instruction at this point.
+       int index = INTVAL ();
+       jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+                                                    index)).o;
+       PUSHA (k);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
     insn_ldc2_w:
       {
        void *where = AVAL2UP ();
index 3869bffd50201e8af103cad658a868ac1229761d..8b9cfcc759fae5dc8dc828087529535f9e068e30 100644 (file)
@@ -1950,13 +1950,16 @@ private:
   {
     check_pool_index (index);
     _Jv_Constants *pool = &current_class->constants;
-    if (pool->tags[index] == JV_CONSTANT_ResolvedString
-       || pool->tags[index] == JV_CONSTANT_String)
+    int tag = pool->tags[index];
+    if (tag == JV_CONSTANT_ResolvedString || tag == JV_CONSTANT_String)
       return type (&java::lang::String::class$, this);
-    else if (pool->tags[index] == JV_CONSTANT_Integer)
+    else if (tag == JV_CONSTANT_Integer)
       return type (int_type);
-    else if (pool->tags[index] == JV_CONSTANT_Float)
+    else if (tag == JV_CONSTANT_Float)
       return type (float_type);
+    else if (current_method->is_15
+            && (tag == JV_CONSTANT_ResolvedClass || tag == JV_CONSTANT_Class))
+      return type (&java::lang::Class::class$, this);
     verify_fail ("String, int, or float constant expected", start_PC);
   }