Add new interceptor for strtonum(3)

Summary:
strtonum(3) reliably convertss string value to an integer.
This function is used in OpenBSD compat namespace
and is located inside NetBSD's libc.

Add a dedicated test for this interface.

It's a reworked version of the original code by Yang Zheng.

Reviewers: joerg, vitalybuka

Reviewed By: vitalybuka

Subscribers: tomsun.0.7, kubamracek, llvm-commits, mgorny, #sanitizers

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D54527

llvm-svn: 348651
This commit is contained in:
Kamil Rytarowski 2018-12-07 21:47:36 +00:00
parent a0082afcb6
commit 0fed92a933
3 changed files with 78 additions and 0 deletions

View File

@ -7728,6 +7728,30 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
#define INIT_MODCTL
#endif
#if SANITIZER_INTERCEPT_STRTONUM
INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
long long maxval, const char **errstr) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);
// TODO(kamil): Implement strtoll as a common inteceptor
char *real_endptr;
long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);
ret = REAL(strtonum)(nptr, minval, maxval, errstr);
if (errstr) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
if (*errstr)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
}
return ret;
}
#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
#else
#define INIT_STRTONUM
#endif
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
@ -7992,6 +8016,7 @@ static void InitializeCommonInterceptors() {
INIT_SYSCTLGETMIBINFO;
INIT_NL_LANGINFO;
INIT_MODCTL;
INIT_STRTONUM;
INIT___PRINTF_CHK;
}

View File

@ -529,5 +529,6 @@
#define SANITIZER_INTERCEPT_SYSCTLGETMIBINFO SI_NETBSD
#define SANITIZER_INTERCEPT_NL_LANGINFO (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_MODCTL SI_NETBSD
#define SANITIZER_INTERCEPT_STRTONUM SI_NETBSD
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

View File

@ -0,0 +1,52 @@
// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s
#define _OPENBSD_SOURCE
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *errstr;
printf("strtonum\n");
long long l = strtonum("100", 1, 100, &errstr);
assert(!errstr);
printf("%lld\n", l);
l = strtonum("200", 1, 100, &errstr);
assert(errstr);
printf("%s\n", errstr);
l = strtonum("300", 1000, 1001, &errstr);
assert(errstr);
printf("%s\n", errstr);
l = strtonum("abc", 1000, 1001, &errstr);
assert(errstr);
printf("%s\n", errstr);
l = strtonum("1000", 1001, 1000, &errstr);
assert(errstr);
printf("%s\n", errstr);
l = strtonum("1000abc", 1000, 1001, &errstr);
assert(errstr);
printf("%s\n", errstr);
l = strtonum("1000.0", 1000, 1001, &errstr);
assert(errstr);
printf("%s\n", errstr);
// CHECK: strtonum
// CHECK: 100
// CHECK: too large
// CHECK: too small
// CHECK: invalid
// CHECK: invalid
// CHECK: invalid
// CHECK: invalid
return 0;
}