diff options
author | Pavel Labath <pavel@labath.sk> | 2019-04-08 08:39:50 +0000 |
---|---|---|
committer | Pavel Labath <pavel@labath.sk> | 2019-04-08 08:39:50 +0000 |
commit | b68b25d43742155cb20177597d970ebeeb0e3dda (patch) | |
tree | 9f8a1ac13f37c5cf28e5925f35ff182fc3237c12 /lib/sanitizer_common/sanitizer_common_interceptors.inc | |
parent | 761390f20ad424b7f9793ff56e58634f78925002 (diff) | |
download | compiler-rt-b68b25d43742155cb20177597d970ebeeb0e3dda.tar.gz |
[Sanitizer] Fix a possible write to freed memory in the wcrtomb interceptor
Summary:
r357240 added an interceptor for wctomb, which uses a temporary local
buffer to make sure we don't write to unallocated memory. This patch
applies the same technique to wcrtomb, and adds some additional tests
for this function.
Reviewers: vitalybuka, eugenis
Subscribers: kubamracek, delcypher, llvm-commits, #sanitizers
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D59984
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@357889 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_common_interceptors.inc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_common_interceptors.inc | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index b3be48d75..bdecf7b0f 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3524,13 +3524,16 @@ INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps); if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); - // FIXME: under ASan the call below may write to freed memory and corrupt - // its metadata. See - // https://github.com/google/sanitizers/issues/321. - SIZE_T res = REAL(wcrtomb)(dest, src, ps); - if (res != ((SIZE_T)-1) && dest) { - SIZE_T write_cnt = res; - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt); + + if (!dest) + return REAL(wcrtomb)(dest, src, ps); + + char local_dest[32]; + SIZE_T res = REAL(wcrtomb)(local_dest, src, ps); + if (res != ((SIZE_T)-1)) { + CHECK_LE(res, sizeof(local_dest)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res); + REAL(memcpy)(dest, local_dest, res); } return res; } |