diff options
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/libfuzzer.go | 30 | ||||
| -rw-r--r-- | src/runtime/libfuzzer_amd64.s | 31 | ||||
| -rw-r--r-- | src/runtime/libfuzzer_arm64.s | 32 |
3 files changed, 90 insertions, 3 deletions
diff --git a/src/runtime/libfuzzer.go b/src/runtime/libfuzzer.go index 920ac575f5..c136eaf5fe 100644 --- a/src/runtime/libfuzzer.go +++ b/src/runtime/libfuzzer.go @@ -9,6 +9,7 @@ package runtime import "unsafe" func libfuzzerCallWithTwoByteBuffers(fn, start, end *byte) +func libfuzzerCall4(fn *byte, fakePC uintptr, s1, s2 unsafe.Pointer, result uintptr) func libfuzzerCall(fn *byte, arg0, arg1 uintptr) func libfuzzerTraceCmp1(arg0, arg1 uint8) { @@ -59,6 +60,31 @@ func init() { libfuzzerCallWithTwoByteBuffers(&__sanitizer_cov_pcs_init, &pcTables[0], &pcTables[size-1]) } +// We call libFuzzer's __sanitizer_weak_hook_strcmp function +// which takes the following four arguments: +// 1- caller_pc: location of string comparison call site +// 2- s1: first string used in the comparison +// 3- s2: second string used in the comparison +// 4- result: an integer representing the comparison result. Libfuzzer only distinguishes between two cases: +// - 0 means that the strings are equal and the comparison will be ignored by libfuzzer. +// - Any other value means that strings are not equal and libfuzzer takes the comparison into consideration. +// Here, we pass 1 when the strings are not equal. +func libfuzzerHookStrCmp(s1, s2 string, fakePC int) { + if s1 != s2 { + libfuzzerCall4(&__sanitizer_weak_hook_strcmp, uintptr(fakePC), cstring(s1), cstring(s2), uintptr(1)) + } + // if s1 == s2 we could call the hook with a last argument of 0 but this is unnecessary since this case will be then + // ignored by libfuzzer +} + +// This function has now the same implementation as libfuzzerHookStrCmp because we lack better checks +// for case-insensitive string equality in the runtime package. +func libfuzzerHookEqualFold(s1, s2 string, fakePC int) { + if s1 != s2 { + libfuzzerCall4(&__sanitizer_weak_hook_strcmp, uintptr(fakePC), cstring(s1), cstring(s2), uintptr(1)) + } +} + //go:linkname __sanitizer_cov_trace_cmp1 __sanitizer_cov_trace_cmp1 //go:cgo_import_static __sanitizer_cov_trace_cmp1 var __sanitizer_cov_trace_cmp1 byte @@ -106,3 +132,7 @@ var __stop___sancov_cntrs byte //go:linkname __sanitizer_cov_pcs_init __sanitizer_cov_pcs_init //go:cgo_import_static __sanitizer_cov_pcs_init var __sanitizer_cov_pcs_init byte + +//go:linkname __sanitizer_weak_hook_strcmp __sanitizer_weak_hook_strcmp +//go:cgo_import_static __sanitizer_weak_hook_strcmp +var __sanitizer_weak_hook_strcmp byte diff --git a/src/runtime/libfuzzer_amd64.s b/src/runtime/libfuzzer_amd64.s index 5ea77f59de..032821fbbc 100644 --- a/src/runtime/libfuzzer_amd64.s +++ b/src/runtime/libfuzzer_amd64.s @@ -13,12 +13,41 @@ #ifdef GOOS_windows #define RARG0 CX #define RARG1 DX +#define RARG0 R8 +#define RARG1 R9 #else #define RARG0 DI #define RARG1 SI +#define RARG2 DX +#define RARG3 CX #endif -// void runtime·libfuzzerCall(fn, arg0, arg1 uintptr) +// void runtime·libfuzzerCall4(fn, hookId int, s1, s2 unsafe.Pointer, result uintptr) +// Calls C function fn from libFuzzer and passes 4 arguments to it. +TEXT runtime·libfuzzerCall4(SB), NOSPLIT, $0-40 + MOVQ fn+0(FP), AX + MOVQ hookId+8(FP), RARG0 + MOVQ s1+16(FP), RARG1 + MOVQ s2+24(FP), RARG2 + MOVQ result+32(FP), RARG3 + + get_tls(R12) + MOVQ g(R12), R14 + MOVQ g_m(R14), R13 + + // Switch to g0 stack. + MOVQ SP, R12 // callee-saved, preserved across the CALL + MOVQ m_g0(R13), R10 + CMPQ R10, R14 + JE call // already on g0 + MOVQ (g_sched+gobuf_sp)(R10), SP +call: + ANDQ $~15, SP // alignment for gcc ABI + CALL AX + MOVQ R12, SP + RET + +// void runtime·libfuzzerCallTraceInit(fn, start, end *byte) // Calls C function fn from libFuzzer and passes 2 arguments to it. TEXT runtime·libfuzzerCall(SB), NOSPLIT, $0-24 MOVQ fn+0(FP), AX diff --git a/src/runtime/libfuzzer_arm64.s b/src/runtime/libfuzzer_arm64.s index b0146682a2..f9b67913e2 100644 --- a/src/runtime/libfuzzer_arm64.s +++ b/src/runtime/libfuzzer_arm64.s @@ -9,12 +9,40 @@ // Based on race_arm64.s; see commentary there. +#define RARG0 R0 +#define RARG1 R1 +#define RARG2 R2 +#define RARG3 R3 + +// void runtime·libfuzzerCall4(fn, hookId int, s1, s2 unsafe.Pointer, result uintptr) +// Calls C function fn from libFuzzer and passes 4 arguments to it. +TEXT runtime·libfuzzerCall4(SB), NOSPLIT, $0-40 + MOVD fn+0(FP), R9 + MOVD hookId+8(FP), RARG0 + MOVD s1+16(FP), RARG1 + MOVD s2+24(FP), RARG2 + MOVD result+32(FP), RARG3 + + MOVD g_m(g), R10 + + // Switch to g0 stack. + MOVD RSP, R19 // callee-saved, preserved across the CALL + MOVD m_g0(R10), R11 + CMP R11, g + BEQ call // already on g0 + MOVD (g_sched+gobuf_sp)(R11), R12 + MOVD R12, RSP +call: + BL R9 + MOVD R19, RSP + RET + // func runtime·libfuzzerCall(fn, arg0, arg1 uintptr) // Calls C function fn from libFuzzer and passes 2 arguments to it. TEXT runtime·libfuzzerCall(SB), NOSPLIT, $0-24 MOVD fn+0(FP), R9 - MOVD arg0+8(FP), R0 - MOVD arg1+16(FP), R1 + MOVD arg0+8(FP), RARG0 + MOVD arg1+16(FP), RARG1 MOVD g_m(g), R10 |
