You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2006/08/10 09:24:52 UTC

svn commit: r430293 - in /db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode: BCClass.java BCMethod.java BCUnsupported.java CodeChunk.java

Author: djd
Date: Thu Aug 10 00:24:49 2006
New Revision: 430293

URL: http://svn.apache.org/viewvc?rev=430293&view=rev
Log:
DERBY-766 (partial) Catch IOExceptions written while generating byte code in CodeChunk
as an exception means a limit of the class file format has been hit and subsequently
the generated code will be invalid. E.g. by trying to represent a invalid constant
pool index which is greater than 64k in two bytes.
Remove the unused class BCUnsupported.

Removed:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCUnsupported.java
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java?rev=430293&r1=430292&r2=430293&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java Thu Aug 10 00:24:49 2006
@@ -372,7 +372,7 @@
 
 		ClassMember method = classHold.addMember(getter, sig, methodModifers);
 
-		CodeChunk chunk = new CodeChunk();
+		CodeChunk chunk = new CodeChunk(this);
 
 		// load 'this' if required
 		if (!staticField)
@@ -396,7 +396,7 @@
 		pda[0] = vmType;
 		sig = new BCMethodDescriptor(pda, VMDescriptor.VOID, factory).toString();
 		method = classHold.addMember(setter, sig, methodModifers);
-		chunk = new CodeChunk();
+		chunk = new CodeChunk(this);
 
 		// load 'this' if required
 		if (!staticField)
@@ -414,7 +414,7 @@
 	
 	/**
 	 * Add the fact that some class limit was exceeded while generating
-	 * the class. We create a set ofg them and report at the end, this
+	 * the class. We create a set of them and report at the end, this
 	 * allows the generated class file to still be dumped.
 	 * @param mb
 	 * @param limitName
@@ -442,5 +442,24 @@
 		
 		limitMsg = sb.toString();
 	}
+    
+    /**
+     * Add the fact that some class limit was exceeded while generating
+     * the class. Text is the simple string passed in.
+     * @param rawText Text to be reported.
+     * 
+     * @see BCClass#addLimitExceeded(BCMethod, String, int, int)
+     */
+    void addLimitExceeded(String rawText)
+    {
+        if (limitMsg != null)
+        {
+            limitMsg = limitMsg + ", " + rawText;
+       }
+        else
+        {
+            limitMsg = rawText;
+        }
+    }
 
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java?rev=430293&r1=430292&r2=430293&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java Thu Aug 10 00:24:49 2006
@@ -163,7 +163,7 @@
 		myEntry = modClass.addMember(methodName, sig, modifiers);
 
 		// get code chunk
-		myCode = new CodeChunk();
+		myCode = new CodeChunk(this.cb);
         
         parameterTypes = parms;
 	}
@@ -1339,7 +1339,7 @@
                 returnType, subMethodName, withParameters ? parameterTypes
                         : null);
         subMethod.thrownExceptions = this.thrownExceptions;
-
+        
         return subMethod;
     }
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java?rev=430293&r1=430292&r2=430293&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java Thu Aug 10 00:24:49 2006
@@ -498,6 +498,15 @@
 	
 	};
 	
+    /**
+     * Assume an IOException means some limit of the class file
+     * format was hit
+     * 
+     */
+    private void limitHit(IOException ioe)
+    {
+        cb.addLimitExceeded(ioe.toString());
+    }
 	
 	
 	/**
@@ -508,6 +517,7 @@
 		try {
 		cout.putU1(opcode);
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 
 		if (SanityManager.DEBUG) {			
@@ -521,10 +531,12 @@
 	 * Add an instruction that has a 16 bit operand.
 	 */
 	void addInstrU2(short opcode, int operand) {
+        
 		try {
 		cout.putU1(opcode);
 		cout.putU2(operand);
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 
 		if (SanityManager.DEBUG) {			
@@ -542,6 +554,7 @@
 		cout.putU1(opcode);
 		cout.putU4(operand);
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 		if (SanityManager.DEBUG) {			
 			if (OPCODE_ACTION[opcode][1] != 5)
@@ -559,6 +572,7 @@
 		cout.putU1(opcode);
 		cout.putU1(operand);
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 
 		// Only debug code from here.
@@ -614,6 +628,7 @@
 		cout.putU1(operand2);
 		cout.putU1(operand3);
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 		if (SanityManager.DEBUG) {			
 			if (OPCODE_ACTION[opcode][1] != 5)
@@ -654,14 +669,22 @@
 	 * @see #insertCodeSpace
 	 */
 	private final int pcDelta;
+    
+    /**
+     * The class we are generating code for, used to indicate that
+     * some limit was hit during code generation.
+     */
+    final BCClass       cb;
 
-	CodeChunk() {
+	CodeChunk(BCClass cb) {
+        this.cb = cb;
         cout = new ClassFormatOutput();
 		try {
 			cout.putU2(0); // max_stack, placeholder for now
 			cout.putU2(0); // max_locals, placeholder for now
 			cout.putU4(0); // code_length, placeholder 4 now
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 		pcDelta = - CodeChunk.CODE_OFFSET;
 	}
@@ -672,10 +695,10 @@
 	 * into an existing stream.
 	 * @param pc
 	 * @param byteCount
-	 * @throws IOException 
 	 */
 	private CodeChunk(CodeChunk main, int pc, int byteCount)
 	{
+        this.cb = main.cb;
 		ArrayOutputStream aos =
 			new ArrayOutputStream(main.cout.getData());
 		
@@ -683,6 +706,7 @@
 			aos.setPosition(CODE_OFFSET + pc);
 			aos.setLimit(byteCount);
 		} catch (IOException e) {
+            limitHit(e);
 		}
 		
 		cout = new ClassFormatOutput(aos);
@@ -706,20 +730,20 @@
 
 		// max_stack is in bytes 0-1
 		if (mb != null && maxStack > 65535)
-			mb.cb.addLimitExceeded(mb, "max_stack", 65535, maxStack);
+			cb.addLimitExceeded(mb, "max_stack", 65535, maxStack);
 			
 		codeBytes[0] = (byte)(maxStack >> 8 );
 		codeBytes[1] = (byte)(maxStack );
 
 		// max_locals is in bytes 2-3
 		if (mb != null && maxLocals > 65535)
-			mb.cb.addLimitExceeded(mb, "max_locals", 65535, maxLocals);
+			cb.addLimitExceeded(mb, "max_locals", 65535, maxLocals);
 		codeBytes[2] = (byte)(maxLocals >> 8 );
 		codeBytes[3] = (byte)(maxLocals );
 
 		// code_length is in bytes 4-7
 		if (mb != null && codeLength > VMOpcode.MAX_CODE_LENGTH)
-			mb.cb.addLimitExceeded(mb, "code_length",
+			cb.addLimitExceeded(mb, "code_length",
 					VMOpcode.MAX_CODE_LENGTH, codeLength);
 		codeBytes[4] = (byte)(codeLength >> 24 );
 		codeBytes[5] = (byte)(codeLength >> 16 );
@@ -767,6 +791,7 @@
 				// attributes is empty, a 0-element array.
 			}
 		} catch (IOException ioe) {
+            limitHit(ioe);
 		}
 
 		fixLengths(mb, maxStack, maxLocals, codeLength);
@@ -1378,7 +1403,7 @@
                 subChunk.cout.write(codeBytes, CODE_OFFSET + split_pc,
                         splitLength);
             } catch (IOException ioe) {
-                // writing to a byte array
+                limitHit(ioe);
             }
 
             // Just cause the sub-method to return,
@@ -1495,7 +1520,7 @@
         // now need to fix up this method, create
         // a new CodeChunk just to be clearer than
         // trying to modify this chunk directly.
-        CodeChunk replaceChunk = new CodeChunk();
+        CodeChunk replaceChunk = new CodeChunk(mb.cb);
         mb.myCode = replaceChunk;
         mb.maxStack = 0;
 
@@ -1507,7 +1532,7 @@
             try {
                 replaceChunk.cout.write(codeBytes, CODE_OFFSET, split_pc);
             } catch (IOException ioe) {
-                // writing to a byte array
+                limitHit(ioe);
             }
         }
 
@@ -1523,9 +1548,16 @@
             replaceChunk.cout.write(codeBytes, CODE_OFFSET + split_pc
                     + splitLength, remainingCodeLength);
         } catch (IOException ioe) {
-            // writing to a byte array
+            limitHit(ioe);
         }
 
+        // Finding the max stack requires the class format to
+        // still be valid. If we have blown the number of constant
+        // pool entries then we can no longer guarantee that indexes
+        // into the constant pool in the code stream are valid.
+        if (cb.limitMsg != null)
+            return -1;
+                
         mb.maxStack = replaceChunk.findMaxStack(ch, 0, replaceChunk.getPC());
 
         return postSplit_pc;