Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support arrays of array #314

Merged
merged 2 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 37 additions & 35 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: tests
on: [push, pull_request]
jobs:
tests:
runs-on: macos-12
runs-on: ubuntu-latest
strategy:
matrix:
api: [26, 27, 28, 29, 30, 31]
Expand All @@ -15,42 +15,44 @@ jobs:
env:
ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: 200 # Default is 20
steps:
# can update to a newer version through https://developer.android.com/studio#downloads
- run: curl https://dl.google.com/android/repository/commandlinetools-mac-8512546_latest.zip -o /tmp/sdk.zip
- run: unzip -d /tmp/sdk /tmp/sdk.zip
- run: mkdir -p ~/Library/Android/Sdk/tools
- run: cp -r /tmp/sdk/cmdline-tools/* ~/Library/Android/Sdk/tools

- run: "echo y | ~/Library/Android/Sdk/tools/bin/sdkmanager tools --sdk_root=~/Library/Android/Sdk"
- run: "~/Library/Android/Sdk/tools/bin/sdkmanager platform-tools --sdk_root=~/Library/Android/Sdk"
- run: "~/Library/Android/Sdk/tools/bin/sdkmanager 'ndk;25.1.8937393' --sdk_root=~/Library/Android/Sdk"
- run: "~/Library/Android/Sdk/tools/bin/sdkmanager 'build-tools;33.0.0' --sdk_root=~/Library/Android/Sdk"

- uses: actions/checkout@v3
- run: |
echo "#!/bin/sh" >> /tmp/android_env
echo "export PATH=$PATH:/Users/runner/Library/Android/Sdk/build-tools/33.0.0" >> /tmp/android_env
echo "export ANDROID_SDK_ROOT=/Users/runner/Library/Android/Sdk" >> /tmp/android_env
echo "export ANDROID_API_LEVEL=${{ matrix.api }}" >> /tmp/android_env
case ${{ matrix.arch }} in
arm64-v8a)
echo "export ANDROID_ARCH=arm64" >> /tmp/android_env
echo "export ANDROID_ABI=arm64-v8a" >> /tmp/android_env
;;
x86)
echo "export ANDROID_ARCH=${{ matrix.arch }}" >> /tmp/android_env
echo "export ANDROID_ABI=${{ matrix.arch }}" >> /tmp/android_env
echo "export ANDROID_LIBDIR=/system/lib" >> /tmp/android_env
;;
*)
echo "export ANDROID_ARCH=${{ matrix.arch }}" >> /tmp/android_env
echo "export ANDROID_ABI=${{ matrix.arch }}" >> /tmp/android_env
;;
esac
chmod +x /tmp/android_env
- name: Check out repo
uses: actions/checkout@v4
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api }}-${{ matrix.arch }}
- name: Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api }}
arch: ${{ matrix.arch }}
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."
- name: Run tests in emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api }}
arch: ${{ matrix.arch }}
script: source /tmp/android_env && make check
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: >-
sdkmanager "platforms;android-${{ matrix.api }}"
&& PATH="$ANDROID_SDK_ROOT/build-tools/34.0.0:$PATH"
ANDROID_ARCH=${{ matrix.arch }}
ANDROID_ABI=${{ matrix.arch }}
ANDROID_API_LEVEL=${{ matrix.api }}
ANDROID_LIBDIR=/system/${{ contains(matrix.arch, '64') && 'lib64' || 'lib' }}
make check
21 changes: 19 additions & 2 deletions lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ const primitiveTypes = {
}
};

const primitiveTypesNames = new Set(Object.values(primitiveTypes).map(t => t.name));

function getPrimitiveType (name) {
const result = primitiveTypes[name];
return (result !== undefined) ? result : null;
Expand Down Expand Up @@ -436,10 +438,27 @@ function getArrayType (typeName, unbox, factory) {
let elementTypeName = typeName.substring(1);
const elementType = getType(elementTypeName, unbox, factory);

let numInternalArrays = 0;
const end = elementTypeName.length;
while (numInternalArrays !== end && elementTypeName[numInternalArrays] === '[') {
numInternalArrays++;
}
elementTypeName = elementTypeName.substring(numInternalArrays);

if (elementTypeName[0] === 'L' && elementTypeName[elementTypeName.length - 1] === ';') {
elementTypeName = elementTypeName.substring(1, elementTypeName.length - 1);
}

// The type name we get is not always the correct representation of the type so we make it so here.
let internalElementTypeName = elementTypeName.replace(/\./g, '/');
if (primitiveTypesNames.has(internalElementTypeName)) {
internalElementTypeName = '['.repeat(numInternalArrays) + internalElementTypeName;
} else {
internalElementTypeName = '['.repeat(numInternalArrays) + 'L' + internalElementTypeName + ';';
}
const internalTypeName = '[' + internalElementTypeName;
elementTypeName = '['.repeat(numInternalArrays) + elementTypeName;

return {
name: typeName.replace(/\./g, '/'),
type: 'pointer',
Expand Down Expand Up @@ -476,8 +495,6 @@ function getArrayType (typeName, unbox, factory) {
}
}

// The type name we get is not always the correct representation of the type so we make it so here.
const internalTypeName = '[L' + elementTypeName.replace(/\./g, '/') + ';';
try {
result.$w = factory.cast(arr, factory.use(internalTypeName), owned);
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion test/config.mk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ANDROID_SDK_ROOT ?= $(shell echo ~/Android/Sdk)
ANDROID_NDK_ROOT ?= $(shell echo ~/.local/opt/android-ndk-r25b
ANDROID_NDK_ROOT ?= $(shell echo ~/.local/opt/android-ndk-r25b)
ANDROID_ARCH ?= arm64
ANDROID_ABI ?= arm64-v8a
ANDROID_API_LEVEL ?= 33
Expand Down
32 changes: 32 additions & 0 deletions test/re/frida/MethodTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ public void primitiveArrayCanBePassed() {
assertEquals("12", script.getNextMessage());
}

@Test
public void primitive2DArrayCanBePassed() {
loadScript("var Buffinator = Java.use('re.frida.Buffinator');" +
"var buffinator = Buffinator.$new();" +
"send(buffinator.sum2d([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));");
assertEquals("45", script.getNextMessage());
}

@Test
public void methodWith2DArrayCanBeHooked() {
loadScript("var Buffinator = Java.use('re.frida.Buffinator');" +
"var sum2d = Buffinator.sum2d;" +
"sum2d.implementation = function (arrs) {" +
"send(JSON.stringify(arrs));" +
"return sum2d.call(this, arrs);" +
"};");
Buffinator buffinator = new Buffinator();
byte[][] arrs = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
assertEquals(45, buffinator.sum2d(arrs));
assertEquals("[[1,2,3],[4,5,6],[7,8,9]]", script.getNextMessage());
}

@Test
public void primitiveArrayCanBeModified() {
loadScript("var Buffinator = Java.use('re.frida.Buffinator');" +
Expand Down Expand Up @@ -620,6 +642,16 @@ public int sum(byte[] values) {
return result;
}

public int sum2d(byte[][] values) {
int result = 0;
for (byte[] array : values) {
for (byte value : array) {
result += value;
}
}
return result;
}

public void bump(int[] values) {
for (int i = 0; i != values.length; i++) {
values[i] += 1000;
Expand Down
Loading