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;