Treat identifiers containing ignorable characters as invalid; Add unit tests for ConverterHelper class.

This commit is contained in:
Maxim Degtyarev
2018-01-23 23:09:09 +03:00
parent 3b6cb5a931
commit f720793431
2 changed files with 143 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.modules.renamer;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer;
import java.util.Arrays;
@@ -29,13 +30,48 @@ public class ConverterHelper implements IIdentifierRenamer {
String value = elementType == Type.ELEMENT_CLASS ? className : element;
return value == null ||
value.length() <= 2 ||
Character.isDigit(value.charAt(0)) ||
!isValidIdentifier(elementType == Type.ELEMENT_METHOD, value) ||
KEYWORDS.contains(value) ||
elementType == Type.ELEMENT_CLASS && (
RESERVED_WINDOWS_NAMESPACE.contains(value.toLowerCase(Locale.US)) ||
value.length() > 255 - ".class".length());
}
/**
* Return {@code true} if, and only if identifier passed is compliant to JLS9 section 3.8 AND DOES NOT CONTAINS so-called "ignorable" characters.
* Ignorable characters are removed by javac silently during compilation and thus may appear only in specially crafted obfuscated classes.
* For more information about "ignorable" characters see <a href="https://bugs.openjdk.java.net/browse/JDK-7144981">JDK-7144981</a>.
*
* @param identifier Identifier to be checked
* @return {@code true} in case {@code identifier} passed can be used as an identifier; {@code false} otherwise.
*/
private static boolean isValidIdentifier(boolean isMethod, String identifier) {
assert identifier != null : "Null identifier passed to the isValidIdentifier() method.";
assert !identifier.isEmpty() : "Empty identifier passed to the isValidIdentifier() method.";
if (isMethod && (identifier.equals(CodeConstants.INIT_NAME) || identifier.equals(CodeConstants.CLINIT_NAME))) {
return true;
}
if (!Character.isJavaIdentifierStart(identifier.charAt(0))) {
return false;
}
char[] chars = identifier.toCharArray();
for(int i = 1; i < chars.length; i++) {
char ch = chars[i];
if ((!Character.isJavaIdentifierPart(ch)) || Character.isIdentifierIgnorable(ch)) {
return false;
}
}
return true;
}
// TODO: consider possible conflicts with not renamed classes, fields and methods!
// We should get all relevant information here.
@Override