I have recently upgraded the Android build tools I use to build an app from 19.1.0 to 21.0.2. The app compiles, but when I start it I get this error:
net.i2p.android W/dalvikvm﹕ Invalid reg type for array index (1103759864)
net.i2p.android W/dalvikvm﹕ VFY: rejected Lnet/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement;.multiply (Lnet/i2p/crypto/eddsa/math/FieldElement;)Lnet/i2p/crypto/eddsa/math/FieldElement;
net.i2p.android W/dalvikvm﹕ VFY: rejecting opcode 0x44 at 0x001c
net.i2p.android W/dalvikvm﹕ VFY: rejected Lnet/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement;.multiply (Lnet/i2p/crypto/eddsa/math/FieldElement;)Lnet/i2p/crypto/eddsa/math/FieldElement;
net.i2p.android W/dalvikvm﹕ Verifier rejected class Lnet/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement;
net.i2p.android W/dalvikvm﹕ Exception Ljava/lang/VerifyError; thrown while initializing Lnet/i2p/crypto/eddsa/spec/EdDSANamedCurveTable;
net.i2p.android W/dalvikvm﹕ Exception Ljava/lang/VerifyError; thrown while initializing Lnet/i2p/crypto/SigType;
net.i2p.android W/dalvikvm﹕ Exception Ljava/lang/VerifyError; thrown while initializing Lnet/i2p/router/startup/CreateRouterInfoJob;
net.i2p.android W/dalvikvm﹕ threadid=12: thread exiting with uncaught exception (group=0x41caeda0)
net.i2p.android E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-6713
Process: net.i2p.android, PID: 26198
java.lang.VerifyError: net/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement
at net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding.decode(Ed25519LittleEndianEncoding.java:189)
at net.i2p.crypto.eddsa.math.Field.fromByteArray(Field.java:55)
at net.i2p.crypto.eddsa.math.Field.<init>(Field.java:39)
at net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable.<clinit>(EdDSANamedCurveTable.java:21)
at net.i2p.crypto.SigType.<clinit>(SigType.java:51)
at net.i2p.router.startup.CreateRouterInfoJob.<clinit>(CreateRouterInfoJob.java:54)
at net.i2p.router.KeyManager$SynchronizeKeysJob.syncKeys(KeyManager.java:156)
at net.i2p.router.KeyManager$SynchronizeKeysJob.runJob(KeyManager.java:146)
at net.i2p.router.KeyManager.startup(KeyManager.java:65)
at net.i2p.router.Router.runRouter(Router.java:468)
at net.i2p.router.Router.main(Router.java:1158)
at net.i2p.router.RouterLaunch.main(RouterLaunch.java:21)
at net.i2p.android.router.service.RouterService$Starter.run(RouterService.java:320)
at java.lang.Thread.run(Thread.java:841)
I am running the app on the same device, and have not changed any code. Why is Dalvik now rejecting this class? I have searched online but have not found anything about the error Invalid reg type for array index
.
The source code of the rejected class is here.
I can't find the specific change in the build tools that surfaced the problem, but after looking at the answer to a different Dalvik problem, I figured out the error.
Dalvik rejects Ed25519FieldElement.multiply()
because it contains 155 local variables. This method was directly ported from corresponding C code, and does not translate well into Java bytecode. It would seem that between 19.1.0 and 21.0.+, the compiler in the build tools was changed in a way that prevents Dalvik from handling this many local variables.
The last post on this page provides some additional insight:
Yep, the Dalvik compiler attempts to assign a "register" to every local variable in the method. It should be able to handle that many, but apparently can't. By making them instance variables you remove the compiler's need/desire to "manage" them (and also make the method a fair amount smaller).
My solution was to remove twenty unnecessary variables (the no-op assignments like g0 = g[0]
), and instead using the arrays directly. This does increase the likelihood of a future bug creeping into the code (if one of the array indices is changed accidentally), but reducing the number of local variables to 135 resolved the runtime class rejection.
The "correct" solution would be to refactor the method entirely to reduce its length. This must be done with care, to avoid introducing side-channel attack vectors.