jode/bytecode/ClassInfo.java.in, jode/bytecode/MethodInfo.java,

jode/bytecode/FieldInfo.java, jode/bytecode/BytecodeInfo.java.in:
	(readAttribute): Never read in known attributes as unknown 
	attributes.  This could happen before when class was first read with
	known info and then again with all info.

jode/obfuscator/ClassIdentifier.java: (doTransformation): Remove
	all unknown attributes.  They may contain references to
	nonexisting constant pool entries.

jode/obfuscator/PackageIdentifier.java: (loadClass): Fix a
	compile time bug in the last patch.


git-svn-id: https://svn.code.sf.net/p/jode/code/branches/branch_1_1@1407 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
hoenicke 18 years ago
parent fca129b90a
commit 240de78e81
  1. 18
      jode/ChangeLog
  2. 152
      jode/jode/bytecode/BytecodeInfo.java.in
  3. 203
      jode/jode/bytecode/ClassInfo.java.in
  4. 15
      jode/jode/bytecode/FieldInfo.java
  5. 9
      jode/jode/bytecode/MethodInfo.java
  6. 4
      jode/jode/obfuscator/ClassIdentifier.java.in
  7. 6
      jode/jode/obfuscator/PackageIdentifier.java.in

@ -1,3 +1,21 @@
2007-07-31 Jochen Hoenicke <hoenicke@gmail.com>
* jode/bytecode/ClassInfo.java.in:
(readAttribute): Never read in known attributes as unknown
attributes. This could happen before when class was first read with
known info and then again with all info.
* jode/bytecode/MethodInfo.java: (readAttribute): Likewise.
* jode/bytecode/FieldInfo.java: (readAttribute): Likewise.
* jode/bytecode/BytecodeInfo.java.in: (readAttribute): Likewise.
* jode/obfuscator/ClassIdentifier.java: (doTransformation): Remove
all unknown attributes. They may contain references to
nonexisting constant pool entries.
* jode/obfuscator/PackageIdentifier.java: (loadClass): Fix a
compile time bug in the last patch.
2005-09-13 Jochen Hoenicke <jochen@gnu.org> 2005-09-13 Jochen Hoenicke <jochen@gnu.org>
Check for NullPointer in SyntheticAnalyzer. Based on Check for NullPointer in SyntheticAnalyzer. Based on

@ -211,90 +211,94 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
protected void readAttribute(String name, int length, ConstantPool cp, protected void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input, DataInputStream input,
int howMuch) throws IOException { int howMuch) throws IOException {
if ((howMuch & KNOWNATTRIBS) != 0 if (name.equals("LocalVariableTable")) {
&& name.equals("LocalVariableTable")) { if ((howMuch & KNOWNATTRIBS) != 0){
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println("LocalVariableTable of "+methodInfo);
int count = input.readUnsignedShort();
if (length != 2 + count * 10) {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0) if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println("Illegal LVT length, ignoring it"); GlobalOptions.err.println("LocalVariableTable of "+methodInfo);
return; int count = input.readUnsignedShort();
} if (length != 2 + count * 10) {
lvt = new LocalVariableInfo[count]; if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
for (int i=0; i < count; i++) { GlobalOptions.err.println("Illegal LVT length, ignoring it");
lvt[i] = new LocalVariableInfo(); return;
int start = input.readUnsignedShort(); }
int end = start + input.readUnsignedShort(); lvt = new LocalVariableInfo[count];
int nameIndex = input.readUnsignedShort(); for (int i=0; i < count; i++) {
int typeIndex = input.readUnsignedShort(); lvt[i] = new LocalVariableInfo();
int slot = input.readUnsignedShort(); int start = input.readUnsignedShort();
Instruction startInstr = int end = start + input.readUnsignedShort();
start >= 0 && start < instrs.length ? instrs[start] : null; int nameIndex = input.readUnsignedShort();
Instruction endInstr; int typeIndex = input.readUnsignedShort();
if (end >=0 && end < instrs.length) int slot = input.readUnsignedShort();
endInstr = instrs[end] == null ? null Instruction startInstr =
: instrs[end].getPrevByAddr(); start >= 0 && start < instrs.length ? instrs[start] : null;
else { Instruction endInstr;
endInstr = null; if (end >=0 && end < instrs.length)
for (int nr = instrs.length - 1; nr >= 0; nr--) { endInstr = instrs[end] == null ? null
if (instrs[nr] != null) { : instrs[end].getPrevByAddr();
if (instrs[nr].getNextAddr() == end) else {
endInstr = instrs[nr]; endInstr = null;
break; for (int nr = instrs.length - 1; nr >= 0; nr--) {
if (instrs[nr] != null) {
if (instrs[nr].getNextAddr() == end)
endInstr = instrs[nr];
break;
}
} }
} }
}
if (startInstr == null if (startInstr == null
|| endInstr == null || endInstr == null
|| nameIndex == 0 || typeIndex == 0 || nameIndex == 0 || typeIndex == 0
|| slot >= maxLocals || slot >= maxLocals
|| cp.getTag(nameIndex) != cp.UTF8 || cp.getTag(nameIndex) != cp.UTF8
|| cp.getTag(typeIndex) != cp.UTF8) { || cp.getTag(typeIndex) != cp.UTF8) {
// This is probably an evil lvt as created by HashJava // This is probably an evil lvt as created by HashJava
// simply ignore it. // simply ignore it.
if ((GlobalOptions.debuggingFlags if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_LVT) != 0) & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println GlobalOptions.err.println
("Illegal entry, ignoring LVT"); ("Illegal entry, ignoring LVT");
lvt = null; lvt = null;
return; return;
}
lvt[i].start = startInstr;
lvt[i].end = endInstr;
lvt[i].name = cp.getUTF8(nameIndex);
lvt[i].type = cp.getUTF8(typeIndex);
lvt[i].slot = slot;
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println("\t" + lvt[i].name + ": "
+ lvt[i].type
+" range "+start+" - "+end
+" slot "+slot);
} }
lvt[i].start = startInstr; } else
lvt[i].end = endInstr; input.readFully(new byte[length]);
lvt[i].name = cp.getUTF8(nameIndex); } else if (name.equals("LineNumberTable")) {
lvt[i].type = cp.getUTF8(typeIndex); if ((howMuch & KNOWNATTRIBS) != 0) {
lvt[i].slot = slot; int count = input.readUnsignedShort();
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0) if (length != 2 + count * 4) {
GlobalOptions.err.println("\t" + lvt[i].name + ": "
+ lvt[i].type
+" range "+start+" - "+end
+" slot "+slot);
}
} else if ((howMuch & KNOWNATTRIBS) != 0
&& name.equals("LineNumberTable")) {
int count = input.readUnsignedShort();
if (length != 2 + count * 4) {
GlobalOptions.err.println
("Illegal LineNumberTable, ignoring it");
return;
}
lnt = new LineNumber[count];
for (int i = 0; i < count; i++) {
lnt[i] = new LineNumber();
int start = input.readUnsignedShort();
Instruction startInstr = instrs[start];
if (startInstr == null) {
GlobalOptions.err.println GlobalOptions.err.println
("Illegal entry, ignoring LineNumberTable table"); ("Illegal LineNumberTable, ignoring it");
lnt = null;
return; return;
} }
lnt[i].start = startInstr; lnt = new LineNumber[count];
lnt[i].linenr = input.readUnsignedShort(); for (int i = 0; i < count; i++) {
} lnt[i] = new LineNumber();
int start = input.readUnsignedShort();
Instruction startInstr = instrs[start];
if (startInstr == null) {
GlobalOptions.err.println
("Illegal entry, ignoring LineNumberTable table");
lnt = null;
return;
}
lnt[i].start = startInstr;
lnt[i].linenr = input.readUnsignedShort();
}
} else
input.readFully(new byte[length]);
} else } else
super.readAttribute(name, length, cp, input, howMuch); super.readAttribute(name, length, cp, input, howMuch);
} }

@ -168,111 +168,116 @@ public class ClassInfo extends BinaryInfo {
ConstantPool cp, ConstantPool cp,
DataInputStream input, DataInputStream input,
int howMuch) throws IOException { int howMuch) throws IOException {
if ((howMuch & KNOWNATTRIBS) != 0 && name.equals("SourceFile")) { if (name.equals("SourceFile")) {
if (length != 2) if ((howMuch & KNOWNATTRIBS) != 0) {
throw new ClassFormatException("SourceFile attribute" if (length != 2)
+ " has wrong length"); throw new ClassFormatException("SourceFile attribute"
sourceFile = cp.getUTF8(input.readUnsignedShort()); + " has wrong length");
} else if ((howMuch & (OUTERCLASSES | INNERCLASSES)) != 0 sourceFile = cp.getUTF8(input.readUnsignedShort());
&& name.equals("InnerClasses")) { } else
int count = input.readUnsignedShort(); input.readFully(new byte[length]);
if (length != 2 + 8 * count) } else if (name.equals("InnerClasses")) {
if ((howMuch & (OUTERCLASSES | INNERCLASSES)) != 0) {
int count = input.readUnsignedShort();
if (length != 2 + 8 * count)
throw new ClassFormatException throw new ClassFormatException
("InnerClasses attribute has wrong length"); ("InnerClasses attribute has wrong length");
int innerCount = 0, outerCount = 0, extraCount = 0; int innerCount = 0, outerCount = 0, extraCount = 0;
InnerClassInfo[] innerClassInfo = new InnerClassInfo[count]; InnerClassInfo[] innerClassInfo = new InnerClassInfo[count];
for (int i=0; i< count; i++) { for (int i=0; i< count; i++) {
int innerIndex = input.readUnsignedShort(); int innerIndex = input.readUnsignedShort();
int outerIndex = input.readUnsignedShort(); int outerIndex = input.readUnsignedShort();
int nameIndex = input.readUnsignedShort(); int nameIndex = input.readUnsignedShort();
String inner = cp.getClassName(innerIndex); String inner = cp.getClassName(innerIndex);
String outer = String outer =
outerIndex != 0 ? cp.getClassName(outerIndex) : null; outerIndex != 0 ? cp.getClassName(outerIndex) : null;
String innername = String innername =
nameIndex != 0 ? cp.getUTF8(nameIndex) : null; nameIndex != 0 ? cp.getUTF8(nameIndex) : null;
int access = input.readUnsignedShort(); int access = input.readUnsignedShort();
if (innername != null && innername.length() == 0) if (innername != null && innername.length() == 0)
innername = null; innername = null;
/* Some compilers give method scope classes a valid /* Some compilers give method scope classes a valid
* outer field, but we mustn't handle them as inner * outer field, but we mustn't handle them as inner
* classes. The best way to distinguish this case * classes. The best way to distinguish this case
* is by the class name. * is by the class name.
*/
if (outer != null && innername != null
&& inner.length() > outer.length() + 2 + innername.length()
&& inner.startsWith(outer+"$")
&& inner.endsWith("$"+innername)
&& Character.isDigit(inner.charAt(outer.length() + 1)))
outer = null;
InnerClassInfo ici = new InnerClassInfo
(inner, outer, innername, access);
if (outer != null && outer.equals(getName())
&& innername != null)
innerClassInfo[innerCount++] = ici;
else
innerClassInfo[count - (++extraCount)] = ici;
}
/* Now innerClasses are at the front of innerClassInfo array
* in correct order. The other InnerClassInfos are in reverse
* order in the rest of the innerClassInfo array.
*/ */
if (outer != null && innername != null
&& inner.length() > outer.length() + 2 + innername.length() /* We now count the outerClasses. The reverse order is the
&& inner.startsWith(outer+"$") * right thing for us.
&& inner.endsWith("$"+innername) */
&& Character.isDigit(inner.charAt(outer.length() + 1))) {
outer = null; String lastOuterName = getName();
for (int i = count - extraCount;
InnerClassInfo ici = new InnerClassInfo i < count && lastOuterName != null; i++) {
(inner, outer, innername, access); InnerClassInfo ici = innerClassInfo[i];
if (ici.inner.equals(lastOuterName)) {
if (outer != null && outer.equals(getName()) outerCount++;
&& innername != null) extraCount--;
innerClassInfo[innerCount++] = ici; lastOuterName = ici.outer;
else }
innerClassInfo[count - (++extraCount)] = ici;
}
/* Now innerClasses are at the front of innerClassInfo array
* in correct order. The other InnerClassInfos are in reverse
* order in the rest of the innerClassInfo array.
*/
/* We now count the outerClasses. The reverse order is the
* right thing for us.
*/
{
String lastOuterName = getName();
for (int i = count - extraCount;
i < count && lastOuterName != null; i++) {
InnerClassInfo ici = innerClassInfo[i];
if (ici.inner.equals(lastOuterName)) {
outerCount++;
extraCount--;
lastOuterName = ici.outer;
} }
} }
} if (innerCount > 0) {
if (innerCount > 0) { innerClasses = new InnerClassInfo[innerCount];
innerClasses = new InnerClassInfo[innerCount]; System.arraycopy(innerClassInfo, 0,
System.arraycopy(innerClassInfo, 0, innerClasses, 0, innerCount);
innerClasses, 0, innerCount); } else
} else innerClasses = null;
innerClasses = null;
if (outerCount > 0) {
if (outerCount > 0) { outerClasses = new InnerClassInfo[outerCount];
outerClasses = new InnerClassInfo[outerCount]; } else
} else outerClasses = null;
outerClasses = null;
if (extraCount > 0) {
if (extraCount > 0) { extraClasses = new InnerClassInfo[extraCount];
extraClasses = new InnerClassInfo[extraCount]; } else
} else extraClasses = null;
extraClasses = null;
/* The last part: We split between outer and extra classes.
/* The last part: We split between outer and extra classes. * In this step we will also revert the order of the extra
* In this step we will also revert the order of the extra * classes.
* classes. */
*/ {
{ int outerPtr = 0;
int outerPtr = 0; String lastOuterName = getName();
String lastOuterName = getName(); for (int i = count - extraCount - outerCount;
for (int i = count - extraCount - outerCount; i < count; i++) {
i < count; i++) { InnerClassInfo ici = innerClassInfo[i];
InnerClassInfo ici = innerClassInfo[i];
/* If we counted correctly there is no NullPointer
/* If we counted correctly there is no NullPointer * or ArrayIndexOutOfBoundsException here
* or ArrayIndexOutOfBoundsException here */
*/ if (ici.inner.equals(lastOuterName)) {
if (ici.inner.equals(lastOuterName)) { outerClasses[outerPtr++] = ici;
outerClasses[outerPtr++] = ici; lastOuterName = ici.outer;
lastOuterName = ici.outer; } else
} else extraClasses[--extraCount] = ici;
extraClasses[--extraCount] = ici; }
} }
} } else
input.readFully(new byte[length]);
} else if (name.equals("Deprecated")) { } else if (name.equals("Deprecated")) {
deprecatedFlag = true; deprecatedFlag = true;
if (length != 0) if (length != 0)

@ -49,12 +49,15 @@ public class FieldInfo extends BinaryInfo {
ConstantPool cp, ConstantPool cp,
DataInputStream input, DataInputStream input,
int howMuch) throws IOException { int howMuch) throws IOException {
if ((howMuch & KNOWNATTRIBS) != 0 && name.equals("ConstantValue")) { if (name.equals("ConstantValue")) {
if (length != 2) if ((howMuch & KNOWNATTRIBS) != 0) {
throw new ClassFormatException("ConstantValue attribute" if (length != 2)
+ " has wrong length"); throw new ClassFormatException("ConstantValue attribute"
int index = input.readUnsignedShort(); + " has wrong length");
constant = cp.getConstant(index); int index = input.readUnsignedShort();
constant = cp.getConstant(index);
} else
input.readFully(new byte[length]);
} else if (name.equals("Synthetic")) { } else if (name.equals("Synthetic")) {
syntheticFlag = true; syntheticFlag = true;
if (length != 0) if (length != 0)

@ -51,9 +51,12 @@ public class MethodInfo extends BinaryInfo {
protected void readAttribute(String name, int length, ConstantPool cp, protected void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input, DataInputStream input,
int howMuch) throws IOException { int howMuch) throws IOException {
if ((howMuch & KNOWNATTRIBS) != 0 && name.equals("Code")) { if (name.equals("Code")) {
bytecode = new BytecodeInfo(this); if ((howMuch & KNOWNATTRIBS) != 0) {
bytecode.read(cp, input); bytecode = new BytecodeInfo(this);
bytecode.read(cp, input);
} else
input.readFully(new byte[length]);
} else if (name.equals("Exceptions")) { } else if (name.equals("Exceptions")) {
int count = input.readUnsignedShort(); int count = input.readUnsignedShort();
exceptions = new String[count]; exceptions = new String[count];

@ -663,6 +663,10 @@ public class ClassIdentifier extends Identifier {
} }
} }
/* Drop unknown attributes.
* They may be broken now anyway due to renaming.
*/
info.dropInfo(info.UNKNOWN_ATTRIBUTES);
info.setFields((FieldInfo[]) newFields.toArray info.setFields((FieldInfo[]) newFields.toArray
(new FieldInfo[newFields.size()])); (new FieldInfo[newFields.size()]));
info.setMethods((MethodInfo[]) newMethods.toArray info.setMethods((MethodInfo[]) newMethods.toArray

@ -102,7 +102,7 @@ public class PackageIdentifier extends Identifier {
loadedClasses.put(subclazz, ident); loadedClasses.put(subclazz, ident);
swappedClasses = null; swappedClasses = null;
bundle.addClassIdentifier(ident); bundle.addClassIdentifier(ident);
((ClassIdentifier) ident).initClass(); ident.initClass();
} }
} }
// Everything is loaded, we don't need to load on demand anymore. // Everything is loaded, we don't need to load on demand anymore.
@ -131,7 +131,7 @@ public class PackageIdentifier extends Identifier {
public ClassIdentifier loadClass(String name) { public ClassIdentifier loadClass(String name) {
int index = name.indexOf('.'); int index = name.indexOf('.');
if (index == -1) { if (index == -1) {
ClassIdentifier ident = (Identifier) loadedClasses.get(name); ClassIdentifier ident = (ClassIdentifier) loadedClasses.get(name);
if (ident == null) { if (ident == null) {
String subFull = String subFull =
(fullName.length() > 0) ? fullName + "."+ name : name; (fullName.length() > 0) ? fullName + "."+ name : name;
@ -156,7 +156,7 @@ public class PackageIdentifier extends Identifier {
loadedClasses.put(name, ident); loadedClasses.put(name, ident);
swappedClasses = null; swappedClasses = null;
bundle.addClassIdentifier(ident); bundle.addClassIdentifier(ident);
((ClassIdentifier) ident).initClass(); ident.initClass();
} }
} }
return ident; return ident;

Loading…
Cancel
Save