mirror of
https://github.com/skylot/jadx.git
synced 2024-11-30 08:00:47 +00:00
core: fix encoded value parser for signed and floating point numbers
This commit is contained in:
parent
1ba19d3600
commit
d94087b939
@ -22,7 +22,7 @@ public class EncValueParser extends EncodedValueReader {
|
||||
}
|
||||
|
||||
public Object parseValue() throws DecodeException {
|
||||
int argAndType = in.readByte() & 0xFF;
|
||||
int argAndType = readByte();
|
||||
int type = argAndType & 0x1F;
|
||||
int arg = (argAndType & 0xE0) >> 5;
|
||||
int size = arg + 1;
|
||||
@ -39,28 +39,29 @@ public class EncValueParser extends EncodedValueReader {
|
||||
case ENCODED_SHORT:
|
||||
return (short) parseNumber(size, true);
|
||||
case ENCODED_CHAR:
|
||||
return (char) parseNumber(size, false);
|
||||
return (char) parseUnsignedInt(size);
|
||||
case ENCODED_INT:
|
||||
return (int) parseNumber(size, true);
|
||||
case ENCODED_LONG:
|
||||
return parseNumber(size, true);
|
||||
|
||||
case ENCODED_FLOAT:
|
||||
return Float.intBitsToFloat((int) parseNumber(size, false));
|
||||
return Float.intBitsToFloat((int) parseNumber(size, false, 4));
|
||||
case ENCODED_DOUBLE:
|
||||
return Double.longBitsToDouble(parseNumber(size, false));
|
||||
return Double.longBitsToDouble(parseNumber(size, false, 8));
|
||||
|
||||
case ENCODED_STRING:
|
||||
return dex.getString((int) parseNumber(size, false));
|
||||
return dex.getString(parseUnsignedInt(size));
|
||||
|
||||
case ENCODED_TYPE:
|
||||
return dex.getType((int) parseNumber(size, false));
|
||||
return dex.getType(parseUnsignedInt(size));
|
||||
|
||||
case ENCODED_METHOD:
|
||||
return MethodInfo.fromDex(dex, (int) parseNumber(size, false));
|
||||
return MethodInfo.fromDex(dex, parseUnsignedInt(size));
|
||||
|
||||
case ENCODED_FIELD:
|
||||
case ENCODED_ENUM:
|
||||
return FieldInfo.fromDex(dex, (int) parseNumber(size, false));
|
||||
return FieldInfo.fromDex(dex, parseUnsignedInt(size));
|
||||
|
||||
case ENCODED_ARRAY:
|
||||
int count = Leb128Utils.readUnsignedLeb128(in);
|
||||
@ -76,18 +77,36 @@ public class EncValueParser extends EncodedValueReader {
|
||||
throw new DecodeException("Unknown encoded value type: 0x" + Integer.toHexString(type));
|
||||
}
|
||||
|
||||
private int parseUnsignedInt(int byteCount) {
|
||||
return (int) parseNumber(byteCount, false, 0);
|
||||
}
|
||||
|
||||
private long parseNumber(int byteCount, boolean isSignExtended) {
|
||||
return parseNumber(byteCount, isSignExtended, 0);
|
||||
}
|
||||
|
||||
private long parseNumber(int byteCount, boolean isSignExtended, int fillOnRight) {
|
||||
long result = 0;
|
||||
int shift = 8;
|
||||
int first = in.readByte() & 0xFF;
|
||||
if (isSignExtended && (first & 0x80) != 0) {
|
||||
result = ~result << shift;
|
||||
long last = 0;
|
||||
for (int i = 0; i < byteCount; i++) {
|
||||
last = readByte();
|
||||
result |= last << i * 8;
|
||||
}
|
||||
result |= (long) first;
|
||||
for (int i = 1; i < byteCount; i++) {
|
||||
result |= (long) (in.readByte() & 0xFF) << shift;
|
||||
shift += 8;
|
||||
if (fillOnRight != 0) {
|
||||
for (int i = byteCount; i < fillOnRight; i++) {
|
||||
result <<= 8;
|
||||
}
|
||||
} else {
|
||||
if (isSignExtended && (last & 0x80) != 0) {
|
||||
for (int i = byteCount; i < 8; i++) {
|
||||
result |= (long) 0xFF << i * 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int readByte() {
|
||||
return in.readByte() & 0xFF;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,15 @@ public class TestAnnotations extends InternalJadxTest {
|
||||
}
|
||||
|
||||
@A(a = -1)
|
||||
public void method1() {
|
||||
public void methodA1() {
|
||||
}
|
||||
|
||||
@A(a = -253)
|
||||
public void methodA2() {
|
||||
}
|
||||
|
||||
@A(a = -11253)
|
||||
public void methodA3() {
|
||||
}
|
||||
|
||||
private static @interface V {
|
||||
@ -25,7 +33,7 @@ public class TestAnnotations extends InternalJadxTest {
|
||||
}
|
||||
|
||||
@V(false)
|
||||
public void method2() {
|
||||
public void methodV() {
|
||||
}
|
||||
|
||||
private static @interface D {
|
||||
@ -33,7 +41,7 @@ public class TestAnnotations extends InternalJadxTest {
|
||||
}
|
||||
|
||||
@D
|
||||
public void method3() {
|
||||
public void methodD() {
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,9 +49,12 @@ public class TestAnnotations extends InternalJadxTest {
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
System.out.println(code);
|
||||
|
||||
assertThat(code, not(containsString("@A(a = 255)")));
|
||||
assertThat(code, containsString("@A(a = -1)"));
|
||||
assertThat(code, containsString("@A(a = -253)"));
|
||||
assertThat(code, containsString("@A(a = -11253)"));
|
||||
assertThat(code, containsString("@V(false)"));
|
||||
assertThat(code, not(containsString("@D()")));
|
||||
}
|
||||
|
@ -28,6 +28,12 @@ public abstract class AbstractTest {
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertEquals(float a1, float a2) {
|
||||
if (Float.compare(a1, a2) != 0) {
|
||||
throw new AssertionError(a1 + " != " + a2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertEquals(Object a1, Object a2) {
|
||||
if (a1 == null) {
|
||||
if (a2 != null)
|
||||
|
@ -0,0 +1,42 @@
|
||||
package jadx.samples;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
public class TestAnnotationsParser extends AbstractTest {
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface A {
|
||||
int i();
|
||||
|
||||
float f();
|
||||
}
|
||||
|
||||
@A(i = -1, f = C1.FLOAT_CONST)
|
||||
public static class C1 {
|
||||
public static final float FLOAT_CONST = 3.14f;
|
||||
}
|
||||
|
||||
@A(i = -1025, f = C2.FLOAT_CONST)
|
||||
public static class C2 {
|
||||
public static final float FLOAT_CONST = 0xFF0000;
|
||||
}
|
||||
|
||||
public boolean testRun() {
|
||||
A c1 = C1.class.getAnnotation(A.class);
|
||||
assertEquals(c1.i(), -1);
|
||||
assertEquals(c1.f(), C1.FLOAT_CONST);
|
||||
|
||||
A c2 = C2.class.getAnnotation(A.class);
|
||||
assertEquals(c2.i(), -1025);
|
||||
assertEquals(c2.f(), C2.FLOAT_CONST);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TestAnnotationsParser().testRun();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user