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>
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,
DataInputStream input,
int howMuch) throws IOException {
if ((howMuch & KNOWNATTRIBS) != 0
&& name.equals("LocalVariableTable")) {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println("LocalVariableTable of "+methodInfo);
int count = input.readUnsignedShort();
if (length != 2 + count * 10) {
if (name.equals("LocalVariableTable")) {
if ((howMuch & KNOWNATTRIBS) != 0){
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println("Illegal LVT length, ignoring it");
return;
}
lvt = new LocalVariableInfo[count];
for (int i=0; i < count; i++) {
lvt[i] = new LocalVariableInfo();
int start = input.readUnsignedShort();
int end = start + input.readUnsignedShort();
int nameIndex = input.readUnsignedShort();
int typeIndex = input.readUnsignedShort();
int slot = input.readUnsignedShort();
Instruction startInstr =
start >= 0 && start < instrs.length ? instrs[start] : null;
Instruction endInstr;
if (end >=0 && end < instrs.length)
endInstr = instrs[end] == null ? null
: instrs[end].getPrevByAddr();
else {
endInstr = null;
for (int nr = instrs.length - 1; nr >= 0; nr--) {
if (instrs[nr] != null) {
if (instrs[nr].getNextAddr() == end)
endInstr = instrs[nr];
break;
GlobalOptions.err.println("LocalVariableTable of "+methodInfo);
int count = input.readUnsignedShort();
if (length != 2 + count * 10) {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println("Illegal LVT length, ignoring it");
return;
}
lvt = new LocalVariableInfo[count];
for (int i=0; i < count; i++) {
lvt[i] = new LocalVariableInfo();
int start = input.readUnsignedShort();
int end = start + input.readUnsignedShort();
int nameIndex = input.readUnsignedShort();
int typeIndex = input.readUnsignedShort();
int slot = input.readUnsignedShort();
Instruction startInstr =
start >= 0 && start < instrs.length ? instrs[start] : null;
Instruction endInstr;
if (end >=0 && end < instrs.length)
endInstr = instrs[end] == null ? null
: instrs[end].getPrevByAddr();
else {
endInstr = null;
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
|| endInstr == null
|| nameIndex == 0 || typeIndex == 0
|| slot >= maxLocals
|| cp.getTag(nameIndex) != cp.UTF8
|| cp.getTag(typeIndex) != cp.UTF8) {
if (startInstr == null
|| endInstr == null
|| nameIndex == 0 || typeIndex == 0
|| slot >= maxLocals
|| cp.getTag(nameIndex) != cp.UTF8
|| cp.getTag(typeIndex) != cp.UTF8) {
// This is probably an evil lvt as created by HashJava
// simply ignore it.
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println
// This is probably an evil lvt as created by HashJava
// simply ignore it.
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_LVT) != 0)
GlobalOptions.err.println
("Illegal entry, ignoring LVT");
lvt = null;
return;
lvt = null;
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;
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);
}
} 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) {
} else
input.readFully(new byte[length]);
} else if (name.equals("LineNumberTable")) {
if ((howMuch & KNOWNATTRIBS) != 0) {
int count = input.readUnsignedShort();
if (length != 2 + count * 4) {
GlobalOptions.err.println
("Illegal entry, ignoring LineNumberTable table");
lnt = null;
("Illegal LineNumberTable, ignoring it");
return;
}
lnt[i].start = startInstr;
lnt[i].linenr = input.readUnsignedShort();
}
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
("Illegal entry, ignoring LineNumberTable table");
lnt = null;
return;
}
lnt[i].start = startInstr;
lnt[i].linenr = input.readUnsignedShort();
}
} else
input.readFully(new byte[length]);
} else
super.readAttribute(name, length, cp, input, howMuch);
}

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

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

@ -51,9 +51,12 @@ public class MethodInfo extends BinaryInfo {
protected void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if ((howMuch & KNOWNATTRIBS) != 0 && name.equals("Code")) {
bytecode = new BytecodeInfo(this);
bytecode.read(cp, input);
if (name.equals("Code")) {
if ((howMuch & KNOWNATTRIBS) != 0) {
bytecode = new BytecodeInfo(this);
bytecode.read(cp, input);
} else
input.readFully(new byte[length]);
} else if (name.equals("Exceptions")) {
int count = input.readUnsignedShort();
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
(new FieldInfo[newFields.size()]));
info.setMethods((MethodInfo[]) newMethods.toArray

@ -102,7 +102,7 @@ public class PackageIdentifier extends Identifier {
loadedClasses.put(subclazz, ident);
swappedClasses = null;
bundle.addClassIdentifier(ident);
((ClassIdentifier) ident).initClass();
ident.initClass();
}
}
// 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) {
int index = name.indexOf('.');
if (index == -1) {
ClassIdentifier ident = (Identifier) loadedClasses.get(name);
ClassIdentifier ident = (ClassIdentifier) loadedClasses.get(name);
if (ident == null) {
String subFull =
(fullName.length() > 0) ? fullName + "."+ name : name;
@ -156,7 +156,7 @@ public class PackageIdentifier extends Identifier {
loadedClasses.put(name, ident);
swappedClasses = null;
bundle.addClassIdentifier(ident);
((ClassIdentifier) ident).initClass();
ident.initClass();
}
}
return ident;

Loading…
Cancel
Save