Created
April 19, 2016 12:32
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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