diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -10371,6 +10371,28 @@ #define INIT_HEXDUMP #endif +#if SANITIZER_INTERCEPT_ARGP_PARSE +INTERCEPTOR(int, argp_parse, const struct argp *argp, int argc, char **argv, + unsigned flags, int *arg_index, void *input) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, argp_parse, argp, argc, argv, flags, arg_index, + input); + for (int i = 0; i < argc; i++) + COMMON_INTERCEPTOR_READ_RANGE(ctx, argv[i], + common_flags()->strict_string_checks + ? internal_strlen(argv[i]) + 1 + : 1); + int res = REAL(argp_parse)(argp, argc, argv, flags, arg_index, input); + if (!res && arg_index) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg_index, sizeof(int)); + return res; +} + +#define INIT_ARGP_PARSE COMMON_INTERCEPT_FUNCTION(argp_parse); +#else +#define INIT_ARGP_PARSE +#endif + #include "sanitizer_common_interceptors_netbsd_compat.inc" static void InitializeCommonInterceptors() { @@ -10690,6 +10712,7 @@ INIT_UNAME; INIT___XUNAME; INIT_HEXDUMP; + INIT_ARGP_PARSE; INIT___PRINTF_CHK; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -592,6 +592,7 @@ #define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD #define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD #define SANITIZER_INTERCEPT_HEXDUMP SI_FREEBSD +#define SANITIZER_INTERCEPT_ARGP_PARSE SI_GLIBC // This macro gives a way for downstream users to override the above // interceptor macros irrespective of the platform they are on. They have diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/argp_parse.c @@ -0,0 +1,17 @@ +// RUN: %clang %s -o %t && %run %t + +#include +#include + +int main() { + char *argv[] = {NULL}; + int argc = 0; + if (argp_parse(NULL, argc, argv, 0, NULL, NULL)) + return EXIT_FAILURE; + int arg_index; + if (argp_parse(NULL, argc, argv, 0, &arg_index, NULL)) + return EXIT_FAILURE; + if (arg_index) + return EXIT_FAILURE; + return EXIT_SUCCESS; +}