Index: sandbox/linux/seccomp-bpf/codegen_unittest.cc |
diff --git a/sandbox/linux/seccomp-bpf/codegen_unittest.cc b/sandbox/linux/seccomp-bpf/codegen_unittest.cc |
index 0539a0d4337f35a8922242cd1661190963a8984e..e4cf6bb0d9fb89efa73b9a3381e910bdddebba2c 100644 |
--- a/sandbox/linux/seccomp-bpf/codegen_unittest.cc |
+++ b/sandbox/linux/seccomp-bpf/codegen_unittest.cc |
@@ -143,12 +143,108 @@ Instruction *SampleProgramComplex(CodeGen *codegen, int *flags) { |
return insn6; |
} |
+Instruction* SampleProgramConfusingTails(CodeGen* codegen, int* flags) { |
+ // This simple program demonstrates https://crbug.com/351103/ |
+ // The two "LOAD 0" instructions are blocks of their own. MergeTails() could |
+ // be tempted to merge them since they are the same. However, they are |
+ // not mergeable because they fall-through to non semantically equivalent |
+ // blocks. |
+ // Without the fix for this bug, this program should trigger the check in |
+ // CompileAndCompare: the serialized graphs from the program and its compiled |
+ // version will differ. |
+ // |
+ // 0) LOAD 1 // ??? |
+ // 1) if A == 0x1; then JMP 2 else JMP 3 |
+ // 2) LOAD 0 // System call number |
+ // 3) if A == 0x2; then JMP 4 else JMP 5 |
+ // 4) LOAD 0 // System call number |
+ // 5) if A == 0x1; then JMP 6 else JMP 7 |
+ // 6) RET 0x50000 // errno = 0 |
+ // 7) RET 0x50001 // errno = 1 |
+ *flags = NO_FLAGS; |
+ |
+ Instruction* i7 = codegen->MakeInstruction(BPF_RET, ErrorCode(1)); |
+ Instruction* i6 = codegen->MakeInstruction(BPF_RET, ErrorCode(0)); |
+ Instruction* i5 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); |
+ Instruction* i4 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i5); |
+ Instruction* i3 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
+ Instruction* i2 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i3); |
+ Instruction* i1 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
+ Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
+ |
+ return i0; |
+} |
+ |
+Instruction* SampleProgramConfusingTailsBasic(CodeGen* codegen, int* flags) { |
+ // Without the fix for https://crbug.com/351103/, (see |
+ // SampleProgramConfusingTails()), this would generate a cyclic graph and |
+ // crash as the two "LOAD 0" instructions would get merged. |
+ // |
+ // 0) LOAD 1 // ??? |
+ // 1) if A == 0x1; then JMP 2 else JMP 3 |
+ // 2) LOAD 0 // System call number |
+ // 3) if A == 0x2; then JMP 4 else JMP 5 |
+ // 4) LOAD 0 // System call number |
+ // 5) RET 0x50001 // errno = 1 |
+ *flags = NO_FLAGS; |
+ |
+ Instruction* i5 = codegen->MakeInstruction(BPF_RET, ErrorCode(1)); |
+ Instruction* i4 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i5); |
+ Instruction* i3 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
+ Instruction* i2 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i3); |
+ Instruction* i1 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
+ Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
+ |
+ return i0; |
+} |
+ |
+Instruction* SampleProgramConfusingTailsMergeable(CodeGen* codegen, |
+ int* flags) { |
+ // This is similar to SampleProgramConfusingTails(), except that |
+ // instructions 2 and 4 are now RET instructions. |
+ // In PointerCompare(), this exercises the path where two blocks are of the |
+ // same length and identical and the last instruction is a JMP or RET, so the |
+ // following blocks don't need to be looked at and the blocks are mergeable. |
+ // |
+ // 0) LOAD 1 // ??? |
+ // 1) if A == 0x1; then JMP 2 else JMP 3 |
+ // 2) RET 0x5002a // errno = 42 |
+ // 3) if A == 0x2; then JMP 4 else JMP 5 |
+ // 4) RET 0x5002a // errno = 42 |
+ // 5) if A == 0x1; then JMP 6 else JMP 7 |
+ // 6) RET 0x50000 // errno = 0 |
+ // 7) RET 0x50001 // errno = 1 |
+ *flags = HAS_MERGEABLE_TAILS; |
+ |
+ Instruction* i7 = codegen->MakeInstruction(BPF_RET, ErrorCode(1)); |
+ Instruction* i6 = codegen->MakeInstruction(BPF_RET, ErrorCode(0)); |
+ Instruction* i5 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); |
+ Instruction* i4 = codegen->MakeInstruction(BPF_RET, ErrorCode(42)); |
+ Instruction* i3 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
+ Instruction* i2 = codegen->MakeInstruction(BPF_RET, ErrorCode(42)); |
+ Instruction* i1 = |
+ codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
+ Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
+ |
+ return i0; |
+} |
+ |
void ForAllPrograms(void (*test)(CodeGenUnittestHelper *, Instruction *, int)){ |
Instruction *(*function_table[])(CodeGen *codegen, int *flags) = { |
SampleProgramOneInstruction, |
SampleProgramSimpleBranch, |
SampleProgramAtypicalBranch, |
SampleProgramComplex, |
+ SampleProgramConfusingTails, |
+ SampleProgramConfusingTailsBasic, |
+ SampleProgramConfusingTailsMergeable, |
}; |
for (size_t i = 0; i < arraysize(function_table); ++i) { |