Skip to content

Instantly share code, notes, and snippets.

@chkwok
Created April 19, 2016 12:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chkwok/333a56ac3b0a09db539bb924b8a12470 to your computer and use it in GitHub Desktop.
Save chkwok/333a56ac3b0a09db539bb924b8a12470 to your computer and use it in GitHub Desktop.
Demo of an array index, long to int cast type confusion error in Android/ART @ 5.0/5.1.
package com.digibites.arm64bugtest;
import java.util.Arrays;
import android.util.Log;
public class Arm64Bug {
private static final String TAG = "Arm64Bug";
/**
* Sort int[]{ dd, cc, bb, aa } into long[]{ (aa,3), (bb, 2), (cc, 1), (dd, 0) } tuples packed into longs.
* The tracking indices are then used to create a remapping array of { 3, 2, 1, 0 }.
* <p>On Arm64 devices running Android 5.x, it crashes on creating the remapping table with the output:</p>
* <pre>
* I/Arm64Bug: Input: dd, cc, bb, aa
* I/Arm64Bug: With indices: dd00000000, cc00000001, bb00000002, aa00000003
* I/Arm64Bug: Sorted: aa00000003, bb00000002, cc00000001, dd00000000
* I/Arm64Bug: Next entry is aa00000003
* A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x2a812d1c918 in tid 5351 (es.arm64bugtest)
* </pre>
* <p>See {@link #getRemappingIndices} for more information</p>
*/
public static void breakStuff() {
int[] input = { 0xdd, 0xcc, 0xbb, 0xaa };
printIntArray("Input", input);
long[] withIndices = addIndices(input);
printLongArray("With indices", withIndices);
long[] sorted = sorted(withIndices);
printLongArray("Sorted", sorted);
int[] indices = getRemappingIndices(sorted);
printIntArray("Indices", indices);
}
/**
* Demonstration of register type confusion. Output[sorted[i]] is 0 .. 3, but when compiled to native code, the
* upper bits of the long are not zeroed and it tries to write to output[0xaa00000003] instead of output[0x3],
* causing a SIGSEGV
*/
private static int[] getRemappingIndices(long[] sorted) {
int[] output = new int[sorted.length];
for (int i = 0; i < sorted.length; i++) {
Log.i(TAG, "Next entry is " + Long.toHexString(sorted[i]));
output[(int) sorted[i]] = i;
}
return output;
}
public static long[] addIndices(int[] input) {
long[] output = new long[input.length];
for (int i = 0; i < input.length; i++) {
output[i] = ((long) input[i] << 32) + i;
}
return output;
}
private static long[] sorted(long[] withIndices) {
long[] output = Arrays.copyOf(withIndices, withIndices.length);
Arrays.sort(output);
return output;
}
/* Printing helpers */
private static void printLongArray(String name, long[] data) {
StringBuilder b = new StringBuilder();
b.append(name);
b.append(": ");
for (int i = 0; i < data.length; i++) {
b.append(Long.toHexString(data[i]));
b.append(", ");
}
Log.i(TAG, b.toString().substring(0, b.length() - 2));
}
private static void printIntArray(String name, int[] data) {
StringBuilder b = new StringBuilder();
b.append(name);
b.append(": ");
for (int i = 0; i < data.length; i++) {
b.append(Integer.toHexString(data[i]));
b.append(", ");
}
Log.i(TAG, b.toString().substring(0, b.length() - 2));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment