/** * Checks that the given string is a valid internal class name. * * @param name * the string to be checked. * @param msg * a message to be used in case of error. */ static void checkInternalName(final String name, final String msg) { if (name == null || name.length() == 0) { throw new IllegalArgumentException("Invalid " + msg + " (must not be null or empty)"); } if (name.charAt(0) == '[') { checkDesc(name, false); } else { checkInternalName(name, 0, -1, msg); } }
@Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 4); checkInternalName(owner, "owner"); checkUnqualifiedName(version, name, "name"); checkDesc(desc, false); super.visitFieldInsn(opcode, owner, name, desc); ++insnCount; }
/** * Checks that a the given substring is a valid type descriptor. * * @param desc * the string to be checked. * @param start * index of the first character of the identifier (inclusive). * @param canBeVoid * <tt>true</tt> if <tt>V</tt> can be considered valid. * @return the index of the last character of the type decriptor, plus one. */ static int checkDesc(final String desc, final int start, final boolean canBeVoid) { if (desc == null || start >= desc.length()) { throw new IllegalArgumentException( "Invalid type descriptor (must not be null or empty)"); } int index; switch (desc.charAt(start)) { case 'V': if (canBeVoid) { return start + 1; } else { throw new IllegalArgumentException("Invalid descriptor: " + desc); } case 'Z': case 'C': case 'B': case 'S': case 'I': case 'F': case 'J': case 'D': return start + 1; case '[': index = start + 1; while (index < desc.length() && desc.charAt(index) == '[') { ++index; } if (index < desc.length()) { return checkDesc(desc, index, false); } else { throw new IllegalArgumentException("Invalid descriptor: " + desc); } case 'L': index = desc.indexOf(';', start); if (index == -1 || index - start < 2) { throw new IllegalArgumentException("Invalid descriptor: " + desc); } try { checkInternalName(desc, start + 1, index, null); } catch (IllegalArgumentException _) { throw new IllegalArgumentException("Invalid descriptor: " + desc); } return index + 1; default: throw new IllegalArgumentException("Invalid descriptor: " + desc); } }
@Override public void visitTypeInsn(final int opcode, final String type) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 3); checkInternalName(type, "type"); if (opcode == Opcodes.NEW && type.charAt(0) == '[') { throw new IllegalArgumentException( "NEW cannot be used to create arrays: " + type); } super.visitTypeInsn(opcode, type); ++insnCount; }
@Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 5); if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) { checkMethodIdentifier(version, name, "name"); } checkInternalName(owner, "owner"); checkMethodDesc(desc); super.visitMethodInsn(opcode, owner, name, desc); ++insnCount; }
/** * Checks a stack frame value. * * @param value * the value to be checked. */ void checkFrameValue(final Object value) { if (value == Opcodes.TOP || value == Opcodes.INTEGER || value == Opcodes.FLOAT || value == Opcodes.LONG || value == Opcodes.DOUBLE || value == Opcodes.NULL || value == Opcodes.UNINITIALIZED_THIS) { return; } if (value instanceof String) { checkInternalName((String) value, "Invalid stack frame value"); return; } if (!(value instanceof Label)) { throw new IllegalArgumentException("Invalid stack frame value: " + value); } else { usedLabels.add((Label) value); } }
@Override public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) { checkStartCode(); checkEndCode(); checkLabel(start, false, "start label"); checkLabel(end, false, "end label"); checkLabel(handler, false, "handler label"); checkNonDebugLabel(start); checkNonDebugLabel(end); checkNonDebugLabel(handler); if (labels.get(start) != null || labels.get(end) != null || labels.get(handler) != null) { throw new IllegalStateException( "Try catch blocks must be visited before their labels"); } if (type != null) { checkInternalName(type, "type"); } super.visitTryCatchBlock(start, end, handler, type); handlers.add(start); handlers.add(end); }