提交 0f808d5c 编写于 作者: S Skylot

fix: resolve char literal incorrect print as string (#856)

上级 f5767dd8
......@@ -4,6 +4,7 @@ public class Consts {
public static final boolean DEBUG = false;
public static final boolean DEBUG_USAGE = false;
public static final boolean DEBUG_TYPE_INFERENCE = false;
public static final boolean DEBUG_OVERLOADED_CASTS = false;
public static final String CLASS_OBJECT = "java.lang.Object";
public static final String CLASS_STRING = "java.lang.String";
......
......@@ -3,7 +3,6 @@ package jadx.core.codegen;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.LiteralArg;
......@@ -71,11 +70,7 @@ public class TypeGen {
case BOOLEAN:
return lit == 0 ? "false" : "true";
case CHAR:
char ch = (char) lit;
if (!NameMapper.isPrintableChar(ch)) {
return Integer.toString(ch);
}
return stringUtils.unescapeChar(ch);
return stringUtils.unescapeChar((char) lit, cast);
case BYTE:
return formatByte(lit, cast);
case SHORT:
......
......@@ -278,13 +278,14 @@ public class MethodInvokeVisitor extends AbstractVisitor {
if (argsCount == 1) {
return mthDetails.getArgTypes();
}
// TODO: try to minimize casts count
parentMth.addComment("JADX DEBUG: Failed to find minimal casts for resolve overloaded methods, cast all args instead"
+ NL + " method: " + mthDetails
+ NL + " arg types: " + compilerVarTypes
+ NL + " candidates:"
+ NL + " " + Utils.listToString(overloadedMethods, NL + " "));
if (Consts.DEBUG_OVERLOADED_CASTS) {
// TODO: try to minimize casts count
parentMth.addComment("JADX DEBUG: Failed to find minimal casts for resolve overloaded methods, cast all args instead"
+ NL + " method: " + mthDetails
+ NL + " arg types: " + compilerVarTypes
+ NL + " candidates:"
+ NL + " " + Utils.listToString(overloadedMethods, NL + " "));
}
// not resolved -> cast all args
return mthDetails.getArgTypes();
}
......
package jadx.core.utils;
import org.jetbrains.annotations.Nullable;
import jadx.api.JadxArgs;
import jadx.core.deobf.NameMapper;
public class StringUtils {
private static final StringUtils DEFAULT_INSTANCE = new StringUtils(new JadxArgs());
......@@ -24,57 +27,74 @@ public class StringUtils {
res.append('"');
for (int i = 0; i < len; i++) {
int c = str.charAt(i) & 0xFFFF;
processChar(c, res);
processCharInsideString(c, res);
}
res.append('"');
return res.toString();
}
public String unescapeChar(char ch) {
if (ch == '\'') {
return "'\\\''";
private void processCharInsideString(int c, StringBuilder res) {
String str = getSpecialStringForChar(c);
if (str != null) {
res.append(str);
return;
}
if (c < 32 || c >= 127 && escapeUnicode) {
res.append("\\u").append(String.format("%04x", c));
} else {
res.append((char) c);
}
StringBuilder res = new StringBuilder();
res.append('\'');
processChar(ch, res);
res.append('\'');
return res.toString();
}
private void processChar(int c, StringBuilder res) {
/**
* Represent single char best way possible
*/
public String unescapeChar(int c, boolean explicitCast) {
if (c == '\'') {
return "'\\''";
}
String str = getSpecialStringForChar(c);
if (str != null) {
return '\'' + str + '\'';
}
if (c >= 127 && escapeUnicode) {
return String.format("'\\u%04x'", c);
}
if (NameMapper.isPrintableChar(c)) {
return "'" + (char) c + '\'';
}
if (explicitCast) {
return "(char) " + c;
}
return String.valueOf(c);
}
public String unescapeChar(char ch) {
return unescapeChar(ch, false);
}
@Nullable
private String getSpecialStringForChar(int c) {
switch (c) {
case '\n':
res.append("\\n");
break;
return "\\n";
case '\r':
res.append("\\r");
break;
return "\\r";
case '\t':
res.append("\\t");
break;
return "\\t";
case '\b':
res.append("\\b");
break;
return "\\b";
case '\f':
res.append("\\f");
break;
return "\\f";
case '\'':
res.append('\'');
break;
return "'";
case '"':
res.append("\\\"");
break;
return "\\\"";
case '\\':
res.append("\\\\");
break;
return "\\\\";
default:
if (c < 32 || c >= 127 && escapeUnicode) {
res.append("\\u").append(String.format("%04x", c));
} else {
res.append((char) c);
}
break;
return null;
}
}
......
......@@ -43,8 +43,9 @@ class StringUtilsTest {
checkCharUnescape('a', "a");
checkCharUnescape(' ', " ");
checkCharUnescape('\n', "\\n");
checkCharUnescape('\'', "\\\'");
checkCharUnescape('\0', "\\u0000");
checkCharUnescape('\'', "\\'");
assertThat(stringUtils.unescapeChar('\0'), is("0"));
}
private void checkCharUnescape(char input, String result) {
......
package jadx.tests.integration.invoke;
import org.junit.jupiter.api.Test;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
public class TestCastInOverloadedInvoke4 extends IntegrationTest {
public static class TestCls {
public String test(String str) {
return str.replace('\n', ' ');
}
}
@Test
public void test() {
noDebugInfo();
assertThat(getClassNode(TestCls.class))
.code()
.containsOne("return str.replace('\\n', ' ');");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册