[libFuzzer] change the output format for the DataFlow tracer

llvm-svn: 333122
This commit is contained in:
Kostya Serebryany 2018-05-23 20:57:11 +00:00
parent d760c20c94
commit 4925392897
2 changed files with 35 additions and 60 deletions

View File

@ -40,23 +40,12 @@
// //
// Example output: // Example output:
// =============== // ===============
// LEN: 5 // F0 11111111111111
// LABELS: 10 // F1 10000000000000
// L7 1 6
// L8 2 7
// L9 3 8
// L10 4 9
// F1 10
// F2 5
// =============== // ===============
// "LEN:" indicates the number of bytes in the input. // "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on.
// "LABELS:" indicates the number of DFSan labels created while running the input. // The byte string is LEN+1 bytes. The last byte is set if the function
// * The labels [1,LEN] correspond to the bytes of the input // depends on the input length.
// (label 1 corresponds to byte 0, and so on)
// * The label LEN+1 corresponds to the input size.
// * The labels [LEN+2,LABELS] correspond to DFSan's union labels.
// "Li j k": describes the label 'i' as a union of labels 'j' and 'k'.
// "Ff l": tells that the function 'f' depends on the label 'l'.
//===----------------------------------------------------------------------===*/ //===----------------------------------------------------------------------===*/
#include <assert.h> #include <assert.h>
@ -79,9 +68,10 @@ static size_t NumFuncs;
static const uintptr_t *FuncsBeg; static const uintptr_t *FuncsBeg;
static __thread size_t CurrentFunc; static __thread size_t CurrentFunc;
static dfsan_label *FuncLabels; // Array of NumFuncs elements. static dfsan_label *FuncLabels; // Array of NumFuncs elements.
static char *PrintableStringForLabel; // InputLen + 2 bytes.
// Prints all instrumented functions. // Prints all instrumented functions.
int PrintFunctions() { static int PrintFunctions() {
// We don't have the symbolizer integrated with dfsan yet. // We don't have the symbolizer integrated with dfsan yet.
// So use backtrace_symbols_fd and pipe it through llvm-symbolizer. // So use backtrace_symbols_fd and pipe it through llvm-symbolizer.
// TODO(kcc): this is pretty ugly and may break in lots of ways. // TODO(kcc): this is pretty ugly and may break in lots of ways.
@ -99,16 +89,27 @@ int PrintFunctions() {
return 0; return 0;
} }
void PrintDataFlow(FILE *Out) { static void SetBytesForLabel(dfsan_label L, char *Bytes) {
fprintf(Out, "LEN: %zd\n", InputLen); if (L <= InputLen) {
fprintf(Out, "LABELS: %zd\n", dfsan_get_label_count()); Bytes[L] = '1';
for (dfsan_label L = InputLen + 2; L <= dfsan_get_label_count(); L++) { } else {
auto *DLI = dfsan_get_label_info(L); auto *DLI = dfsan_get_label_info(L);
fprintf(Out, "L%d %d %d\n", L, DLI->l1, DLI->l2); SetBytesForLabel(DLI->l1, Bytes);
SetBytesForLabel(DLI->l2, Bytes);
} }
}
static char *GetPrintableStringForLabel(dfsan_label L) {
memset(PrintableStringForLabel, '0', InputLen + 1);
PrintableStringForLabel[InputLen + 1] = 0;
SetBytesForLabel(L, PrintableStringForLabel);
return PrintableStringForLabel;
}
static void PrintDataFlow(FILE *Out) {
for (size_t I = 0; I < NumFuncs; I++) for (size_t I = 0; I < NumFuncs; I++)
if (FuncLabels[I]) if (FuncLabels[I])
fprintf(Out, "F%zd %d\n", I, FuncLabels[I]); fprintf(Out, "F%zd %s\n", I, GetPrintableStringForLabel(FuncLabels[I]));
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -128,6 +129,7 @@ int main(int argc, char **argv) {
unsigned char *Buf = (unsigned char*)malloc(InputLen); unsigned char *Buf = (unsigned char*)malloc(InputLen);
size_t NumBytesRead = fread(Buf, 1, InputLen, In); size_t NumBytesRead = fread(Buf, 1, InputLen, In);
assert(NumBytesRead == InputLen); assert(NumBytesRead == InputLen);
PrintableStringForLabel = (char*)malloc(InputLen + 2);
fclose(In); fclose(In);
fprintf(stderr, "INFO: running '%s'\n", Input); fprintf(stderr, "INFO: running '%s'\n", Input);

View File

@ -24,58 +24,31 @@ RUN: echo -n 1234567890123456 > %t/IN/1234567890123456
# ABC: No data is used, the only used label is 4 (corresponds to the size) # ABC: No data is used, the only used label is 4 (corresponds to the size)
RUN:%t-ThreeFunctionsTestDF %t/IN/ABC | FileCheck %s --check-prefix=IN_ABC RUN:%t-ThreeFunctionsTestDF %t/IN/ABC | FileCheck %s --check-prefix=IN_ABC
IN_ABC: LEN: 3 IN_ABC: F{{[012]}} 1000
IN_ABC: LABELS: 4
IN_ABC: F{{[012]}} 4
IN_ABC-NOT: F IN_ABC-NOT: F
# FUABC: First 3 bytes are checked, Func1/Func2 are not called. # FUABC: First 3 bytes are checked, Func1/Func2 are not called.
RUN:%t-ThreeFunctionsTestDF %t/IN/FUABC | FileCheck %s --check-prefix=IN_FUABC RUN:%t-ThreeFunctionsTestDF %t/IN/FUABC | FileCheck %s --check-prefix=IN_FUABC
IN_FUABC: LEN: 5 IN_FUABC: F{{[012]}} 111100
IN_FUABC: LABELS:
IN_FUABC: L{{.*}} 1
IN_FUABC: L{{.*}} 2
IN_FUABC: L{{.*}} 3
IN_FUABC-NOT: L{{.*}} 4
IN_FUABC: F{{[012]}}
IN_FUABC-NOT: F IN_FUABC-NOT: F
# FUZZR: 5 bytes are used (4 in one function, 5-th in the other), Func2 is not called. # FUZZR: 5 bytes are used (4 in one function, 5-th in the other), Func2 is not called.
RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZR | FileCheck %s --check-prefix=IN_FUZZR RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZR | FileCheck %s --check-prefix=IN_FUZZR
IN_FUZZR: LEN: 5 IN_FUZZR-DAG: F{{[012]}} 111110
IN_FUZZR: LABELS: IN_FUZZR-DAG: F{{[012]}} 000001
IN_FUZZR: L{{.*}} 1
IN_FUZZR: L{{.*}} 2
IN_FUZZR: L{{.*}} 3
IN_FUZZR: L[[L0:[0-9]*]] 4
IN_FUZZR-DAG: F{{[012]}} 5
IN_FUZZR-DAG: F{{[012]}} [[L0]]
IN_FUZZR-NOT: F IN_FUZZR-NOT: F
# FUZZM: 5 bytes are used, both Func1 and Func2 are called, Func2 depends only on size (label 6). # FUZZM: 5 bytes are used, both Func1 and Func2 are called, Func2 depends only on size (label 6).
RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZM | FileCheck %s --check-prefix=IN_FUZZM RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZM | FileCheck %s --check-prefix=IN_FUZZM
IN_FUZZM: LEN: 5 IN_FUZZM-DAG: F{{[012]}} 100000
IN_FUZZM: LABELS: IN_FUZZM-DAG: F{{[012]}} 111110
IN_FUZZM: L{{.*}} 1 IN_FUZZM-DAG: F{{[012]}} 000001
IN_FUZZM: L{{.*}} 2
IN_FUZZM: L{{.*}} 3
IN_FUZZM: L{{.*}} 4
IN_FUZZM-DAG: F{{[012]}} 6
IN_FUZZM-DAG: F{{[012]}} 5
IN_FUZZM-DAG: F
# FUZZMU: 6 bytes are used, both Func1 and Func2 are called, Func2 depends on byte 6 and size (label 7) # FUZZMU: 6 bytes are used, both Func1 and Func2 are called, Func2 depends on byte 6 and size (label 7)
RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZMU | FileCheck %s --check-prefix=IN_FUZZMU RUN:%t-ThreeFunctionsTestDF %t/IN/FUZZMU | FileCheck %s --check-prefix=IN_FUZZMU
IN_FUZZMU: LEN: 6 IN_FUZZMU-DAG: F{{[012]}} 1000001
IN_FUZZMU: LABELS: IN_FUZZMU-DAG: F{{[012]}} 1111100
IN_FUZZMU: L{{.*}} 1 IN_FUZZMU-DAG: F{{[012]}} 0000010
IN_FUZZMU: L{{.*}} 2
IN_FUZZMU: L{{.*}} 3
IN_FUZZMU: L{{.*}} 4
IN_FUZZMU: L[[L2:[0-9]*]] 6 7
IN_FUZZMU-DAG: F{{[012]}} 5
IN_FUZZMU-DAG: F{{[012]}} [[L2]]
IN_FUZZMU-DAG: F
# Today a very simple test will cause DFSan to die with "out of labels" # Today a very simple test will cause DFSan to die with "out of labels"
RUN: not %t-ExplodeDFSanLabelsTestDF %t/IN/1234567890123456 2>&1 | FileCheck %s --check-prefix=OUT_OF_LABELS RUN: not %t-ExplodeDFSanLabelsTestDF %t/IN/1234567890123456 2>&1 | FileCheck %s --check-prefix=OUT_OF_LABELS