Merge "Adjust APF interpreter tests to match APFv4" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-04-20 11:41:52 +00:00
committed by Android (Google) Code Review
3 changed files with 42 additions and 25 deletions

View File

@@ -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
* {@code register}. The source address is computed by adding @{code offset} to the other
* register.
* {@code register}. The source address is computed by adding the signed immediate
* @{code offset} to the other register.
* Requires APF v3 or greater.
*/
public ApfGenerator addLoadData(Register destinationRegister, int offset)
throws IllegalInstructionException {
requireApfVersion(3);
Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
instruction.setUnsignedImm(offset);
instruction.setSignedImm(offset);
addInstruction(instruction);
return this;
}
/**
* 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
* register.
* data memory. The destination address is computed by adding the signed immediate
* @{code offset} to the other register.
* Requires APF v3 or greater.
*/
public ApfGenerator addStoreData(Register sourceRegister, int offset)
throws IllegalInstructionException {
requireApfVersion(3);
Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
instruction.setUnsignedImm(offset);
instruction.setSignedImm(offset);
addInstruction(instruction);
return this;
}

View File

@@ -160,7 +160,7 @@ public class ApfTest {
throw new Exception(
"program: " + HexDump.toHexString(program) +
"\ndata memory: " + HexDump.toHexString(data) +
"\nexpected: " + HexDump.toHexString(expected_data));
"\nexpected: " + HexDump.toHexString(expected_data));
}
}
@@ -625,18 +625,19 @@ public class ApfTest {
@Test
public void testApfDataWrite() throws IllegalInstructionException, Exception {
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();
// No memory access instructions: should leave the data segment untouched.
ApfGenerator gen = new ApfGenerator(3);
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.addLoadImmediate(Register.R0, 0x87654321);
gen.addLoadImmediate(Register.R1, 2);
gen.addStoreData(Register.R0, 3);
gen.addLoadImmediate(Register.R1, -5);
gen.addStoreData(Register.R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16)
expected_data[5] = (byte)0x87;
expected_data[6] = (byte)0x65;
expected_data[7] = (byte)0x43;
@@ -646,16 +647,16 @@ public class ApfTest {
@Test
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);
gen.addLoadImmediate(Register.R1, 3);
gen.addLoadData(Register.R0, 7);
gen.addLoadImmediate(Register.R1, 10);
gen.addLoadData(Register.R0, -16); // 10 + -16 = -6 (offset +10 with data_len=16)
gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
byte[] program = gen.generate();
byte[] packet = new byte[MIN_PKT_SIZE];
// Content is incorrect (last byte does not match) -> PASS
byte[] data = new byte[32];
byte[] data = new byte[16];
data[10] = (byte)0x87;
data[11] = (byte)0x65;
data[12] = (byte)0x43;
@@ -672,10 +673,10 @@ public class ApfTest {
@Test
public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
ApfGenerator gen = new ApfGenerator(3);
gen.addLoadImmediate(Register.R1, 3);
gen.addLoadData(Register.R0, 7); // Load from address 7 + 3 = 10
gen.addLoadImmediate(Register.R1, -22);
gen.addLoadData(Register.R0, 0); // Load from address 32 -22 + 0 = 10
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[] data = new byte[32];
@@ -718,10 +719,17 @@ public class ApfTest {
gen.addJump(gen.DROP_LABEL);
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.addLoadImmediate(Register.R0, 20);
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.
assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
}

View File

@@ -36,11 +36,20 @@ static jint com_android_server_ApfTest_apfSimulate(
uint32_t program_len = env->GetArrayLength(program);
uint32_t packet_len = env->GetArrayLength(packet);
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) {
memcpy(data_raw, program_and_data + program_len, data_len);
env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */);
}
free(program_and_data);
env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT);
env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT);
return result;
@@ -109,8 +118,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js
jstring jpcap_filename, jbyteArray japf_program) {
ScopedUtfChars filter(env, jfilter);
ScopedUtfChars pcap_filename(env, jpcap_filename);
const uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL);
const uint32_t apf_program_len = env->GetArrayLength(japf_program);
uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL);
uint32_t apf_program_len = env->GetArrayLength(japf_program);
// Open pcap file for BPF filtering
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 {
apf_packet = pcap_next(apf_pcap.get(), &apf_header);
} while (apf_packet != NULL && !accept_packet(
apf_program, apf_program_len, apf_packet, apf_header.len,
nullptr, 0, 0));
apf_program, apf_program_len, 0 /* data_len */,
apf_packet, apf_header.len, 0 /* filter_age */));
// Make sure both filters matched the same packet.
if (apf_packet == NULL && bpf_packet == NULL)