Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e56afce9 authored by Bernie Innocenti's avatar Bernie Innocenti Committed by android-build-merger
Browse files

Merge "Adjust APF interpreter tests to match APFv4"

am: 05011abf

Change-Id: I5ca2b41ab6c101bef7465229270079c81743c757
parents 5124d28e 05011abf
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -841,30 +841,30 @@ public class ApfGenerator {


    /**
    /**
     * Add an instruction to the end of the program to load 32 bits from the data memory into
     * Add an instruction to the end of the program to load 32 bits from the data memory into
     * {@code register}. The source address is computed by adding @{code offset} to the other
     * {@code register}. The source address is computed by adding the signed immediate
     * register.
     * @{code offset} to the other register.
     * Requires APF v3 or greater.
     * Requires APF v3 or greater.
     */
     */
    public ApfGenerator addLoadData(Register destinationRegister, int offset)
    public ApfGenerator addLoadData(Register destinationRegister, int offset)
            throws IllegalInstructionException {
            throws IllegalInstructionException {
        requireApfVersion(3);
        requireApfVersion(3);
        Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
        Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
        instruction.setUnsignedImm(offset);
        instruction.setSignedImm(offset);
        addInstruction(instruction);
        addInstruction(instruction);
        return this;
        return this;
    }
    }


    /**
    /**
     * Add an instruction to the end of the program to store 32 bits from {@code register} into the
     * Add an instruction to the end of the program to store 32 bits from {@code register} into the
     * data memory. The destination address is computed by adding @{code offset} to the other
     * data memory. The destination address is computed by adding the signed immediate
     * register.
     * @{code offset} to the other register.
     * Requires APF v3 or greater.
     * Requires APF v3 or greater.
     */
     */
    public ApfGenerator addStoreData(Register sourceRegister, int offset)
    public ApfGenerator addStoreData(Register sourceRegister, int offset)
            throws IllegalInstructionException {
            throws IllegalInstructionException {
        requireApfVersion(3);
        requireApfVersion(3);
        Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
        Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
        instruction.setUnsignedImm(offset);
        instruction.setSignedImm(offset);
        addInstruction(instruction);
        addInstruction(instruction);
        return this;
        return this;
    }
    }
+21 −13
Original line number Original line Diff line number Diff line
@@ -625,18 +625,19 @@ public class ApfTest {
    @Test
    @Test
    public void testApfDataWrite() throws IllegalInstructionException, Exception {
    public void testApfDataWrite() throws IllegalInstructionException, Exception {
        byte[] packet = new byte[MIN_PKT_SIZE];
        byte[] packet = new byte[MIN_PKT_SIZE];
        byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        byte[] expected_data = data.clone();
        byte[] expected_data = data.clone();


        // No memory access instructions: should leave the data segment untouched.
        // No memory access instructions: should leave the data segment untouched.
        ApfGenerator gen = new ApfGenerator(3);
        ApfGenerator gen = new ApfGenerator(3);
        assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
        assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);


        // Expect value 0x87654321 to be stored starting from address 3 + 2, in big-endian order.
        // Expect value 0x87654321 to be stored starting from address -11 from the end of the
        // data buffer, in big-endian order.
        gen = new ApfGenerator(3);
        gen = new ApfGenerator(3);
        gen.addLoadImmediate(Register.R0, 0x87654321);
        gen.addLoadImmediate(Register.R0, 0x87654321);
        gen.addLoadImmediate(Register.R1, 2);
        gen.addLoadImmediate(Register.R1, -5);
        gen.addStoreData(Register.R0, 3);
        gen.addStoreData(Register.R0, -6);  // -5 + -6 = -11 (offset +5 with data_len=16)
        expected_data[5] = (byte)0x87;
        expected_data[5] = (byte)0x87;
        expected_data[6] = (byte)0x65;
        expected_data[6] = (byte)0x65;
        expected_data[7] = (byte)0x43;
        expected_data[7] = (byte)0x43;
@@ -646,16 +647,16 @@ public class ApfTest {


    @Test
    @Test
    public void testApfDataRead() throws IllegalInstructionException, Exception {
    public void testApfDataRead() throws IllegalInstructionException, Exception {
        // Program that DROPs if address 11 (7 + 3) contains 0x87654321.
        // Program that DROPs if address 10 (-6) contains 0x87654321.
        ApfGenerator gen = new ApfGenerator(3);
        ApfGenerator gen = new ApfGenerator(3);
        gen.addLoadImmediate(Register.R1, 3);
        gen.addLoadImmediate(Register.R1, 10);
        gen.addLoadData(Register.R0, 7);
        gen.addLoadData(Register.R0, -16);  // 10 + -16 = -6 (offset +10 with data_len=16)
        gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
        gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
        byte[] program = gen.generate();
        byte[] program = gen.generate();
        byte[] packet = new byte[MIN_PKT_SIZE];
        byte[] packet = new byte[MIN_PKT_SIZE];


        // Content is incorrect (last byte does not match) -> PASS
        // Content is incorrect (last byte does not match) -> PASS
        byte[] data = new byte[32];
        byte[] data = new byte[16];
        data[10] = (byte)0x87;
        data[10] = (byte)0x87;
        data[11] = (byte)0x65;
        data[11] = (byte)0x65;
        data[12] = (byte)0x43;
        data[12] = (byte)0x43;
@@ -672,10 +673,10 @@ public class ApfTest {
    @Test
    @Test
    public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
    public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
        ApfGenerator gen = new ApfGenerator(3);
        ApfGenerator gen = new ApfGenerator(3);
        gen.addLoadImmediate(Register.R1, 3);
        gen.addLoadImmediate(Register.R1, -22);
        gen.addLoadData(Register.R0, 7);  // Load from address 7 + 3 = 10
        gen.addLoadData(Register.R0, 0);  // Load from address 32 -22 + 0 = 10
        gen.addAdd(0x78453412);  // 87654321 + 78453412 = FFAA7733
        gen.addAdd(0x78453412);  // 87654321 + 78453412 = FFAA7733
        gen.addStoreData(Register.R0, 11);  // Write back to address 11 + 3 = 14
        gen.addStoreData(Register.R0, 4);  // Write back to address 32 -22 + 4 = 14


        byte[] packet = new byte[MIN_PKT_SIZE];
        byte[] packet = new byte[MIN_PKT_SIZE];
        byte[] data = new byte[32];
        byte[] data = new byte[32];
@@ -718,10 +719,17 @@ public class ApfTest {
        gen.addJump(gen.DROP_LABEL);
        gen.addJump(gen.DROP_LABEL);
        assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
        assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);


        // ...but underflowing isn't allowed.
        // ...and underflowing simply wraps around to the end of the buffer...
        gen = new ApfGenerator(3);
        gen = new ApfGenerator(3);
        gen.addLoadImmediate(Register.R0, 20);
        gen.addLoadImmediate(Register.R0, 20);
        gen.addLoadData(Register.R1, -30);
        gen.addLoadData(Register.R1, -30);
        gen.addJump(gen.DROP_LABEL);
        assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);

        // ...but doesn't allow accesses before the start of the buffer
        gen = new ApfGenerator(3);
        gen.addLoadImmediate(Register.R0, 20);
        gen.addLoadData(Register.R1, -1000);
        gen.addJump(gen.DROP_LABEL);  // Not reached.
        gen.addJump(gen.DROP_LABEL);  // Not reached.
        assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
        assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
    }
    }
+15 −6
Original line number Original line Diff line number Diff line
@@ -36,11 +36,20 @@ static jint com_android_server_ApfTest_apfSimulate(
    uint32_t program_len = env->GetArrayLength(program);
    uint32_t program_len = env->GetArrayLength(program);
    uint32_t packet_len = env->GetArrayLength(packet);
    uint32_t packet_len = env->GetArrayLength(packet);
    uint32_t data_len = data ? env->GetArrayLength(data) : 0;
    uint32_t data_len = data ? env->GetArrayLength(data) : 0;
    jint result = accept_packet(program_raw, program_len, packet_raw,

                                packet_len, data_raw, data_len, filter_age);
    // Merge program and data into a single buffer.
    uint8_t* program_and_data = (uint8_t*)malloc(program_len + data_len);
    memcpy(program_and_data, program_raw, program_len);
    memcpy(program_and_data + program_len, data_raw, data_len);

    jint result =
        accept_packet(program_and_data, program_len, program_len + data_len,
                      packet_raw, packet_len, filter_age);
    if (data) {
    if (data) {
        memcpy(data_raw, program_and_data + program_len, data_len);
        env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */);
        env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */);
    }
    }
    free(program_and_data);
    env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT);
    env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT);
    env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT);
    env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT);
    return result;
    return result;
@@ -109,8 +118,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js
        jstring jpcap_filename, jbyteArray japf_program) {
        jstring jpcap_filename, jbyteArray japf_program) {
    ScopedUtfChars filter(env, jfilter);
    ScopedUtfChars filter(env, jfilter);
    ScopedUtfChars pcap_filename(env, jpcap_filename);
    ScopedUtfChars pcap_filename(env, jpcap_filename);
    const uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL);
    uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL);
    const uint32_t apf_program_len = env->GetArrayLength(japf_program);
    uint32_t apf_program_len = env->GetArrayLength(japf_program);


    // Open pcap file for BPF filtering
    // Open pcap file for BPF filtering
    ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb"));
    ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb"));
@@ -152,8 +161,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js
        do {
        do {
            apf_packet = pcap_next(apf_pcap.get(), &apf_header);
            apf_packet = pcap_next(apf_pcap.get(), &apf_header);
        } while (apf_packet != NULL && !accept_packet(
        } while (apf_packet != NULL && !accept_packet(
                apf_program, apf_program_len, apf_packet, apf_header.len,
                apf_program, apf_program_len, 0 /* data_len */,
                nullptr, 0, 0));
                apf_packet, apf_header.len, 0 /* filter_age */));


        // Make sure both filters matched the same packet.
        // Make sure both filters matched the same packet.
        if (apf_packet == NULL && bpf_packet == NULL)
        if (apf_packet == NULL && bpf_packet == NULL)