1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/asan_crt_interceptors.h"
16 :
17 : #include <algorithm>
18 :
19 : #include "base/logging.h"
20 : #include "syzygy/agent/asan/asan_rtl_utils.h"
21 : #include "syzygy/agent/asan/error_info.h"
22 : #include "syzygy/agent/asan/shadow.h"
23 :
24 : namespace {
25 :
26 : using agent::asan::Shadow;
27 : using agent::asan::TestMemoryRange;
28 :
29 : } // namespace
30 :
31 : extern "C" {
32 :
33 : void* __cdecl asan_memcpy(unsigned char* destination,
34 : const unsigned char* source,
35 E : size_t num) {
36 E : TestMemoryRange(source, num, agent::asan::ASAN_READ_ACCESS);
37 E : TestMemoryRange(destination, num, agent::asan::ASAN_WRITE_ACCESS);
38 E : return ::memcpy(destination, source, num);
39 E : }
40 :
41 : void* __cdecl asan_memmove(unsigned char* destination,
42 : const unsigned char* source,
43 E : size_t num) {
44 E : TestMemoryRange(source, num, agent::asan::ASAN_READ_ACCESS);
45 E : TestMemoryRange(destination, num, agent::asan::ASAN_WRITE_ACCESS);
46 E : return ::memmove(destination, source, num);
47 E : }
48 :
49 E : void* __cdecl asan_memset(unsigned char* ptr, int value, size_t num) {
50 E : TestMemoryRange(ptr, num, agent::asan::ASAN_WRITE_ACCESS);
51 E : return ::memset(ptr, value, num);
52 E : }
53 :
54 : const void* __cdecl asan_memchr(const unsigned char* ptr,
55 : int value,
56 E : size_t num) {
57 E : TestMemoryRange(ptr, num, agent::asan::ASAN_READ_ACCESS);
58 E : return ::memchr(ptr, value, num);
59 E : }
60 :
61 i : size_t __cdecl asan_strcspn(const char* str1, const char* str2) {
62 : // TODO(sebmarchand): Provide an implementation that guarantees the same
63 : // behavior as the original function.
64 i : NOTIMPLEMENTED();
65 i : return 0;
66 i : }
67 :
68 E : size_t __cdecl asan_strlen(const char* str) {
69 E : size_t size = 0;
70 E : if (!agent::asan::Shadow::GetNullTerminatedArraySize<char>(str, 0U, &size)) {
71 : ReportBadAccess(reinterpret_cast<const uint8*>(str) + size,
72 E : agent::asan::ASAN_READ_ACCESS);
73 E : return ::strlen(str);
74 : }
75 E : return size - 1;
76 E : }
77 :
78 E : const char* __cdecl asan_strrchr(const char* str, int character) {
79 E : size_t size = 0;
80 E : if (!agent::asan::Shadow::GetNullTerminatedArraySize<char>(str, 0U, &size)) {
81 : ReportBadAccess(reinterpret_cast<const uint8*>(str) + size,
82 E : agent::asan::ASAN_READ_ACCESS);
83 : }
84 E : return ::strrchr(str, character);
85 E : }
86 :
87 E : const wchar_t* asan_wcsrchr(const wchar_t* str, wchar_t character) {
88 E : size_t size = 0;
89 : if (!agent::asan::Shadow::GetNullTerminatedArraySize<wchar_t>(str,
90 : 0U,
91 E : &size)) {
92 : ReportBadAccess(reinterpret_cast<const uint8*>(str) + size,
93 E : agent::asan::ASAN_READ_ACCESS);
94 : }
95 E : return ::wcsrchr(str, character);
96 E : }
97 :
98 E : const wchar_t* asan_wcsstr(const wchar_t* str, const wchar_t* keys) {
99 E : size_t size = 0;
100 : if (!agent::asan::Shadow::GetNullTerminatedArraySize<wchar_t>(keys,
101 : 0U,
102 E : &size)) {
103 : ReportBadAccess(reinterpret_cast<const uint8*>(keys) + size,
104 E : agent::asan::ASAN_READ_ACCESS);
105 : }
106 E : const wchar_t* ret = ::wcsstr(str, keys);
107 E : if (ret != NULL && !agent::asan::Shadow::IsAccessible(ret)) {
108 : ReportBadAccess(reinterpret_cast<const uint8*>(ret),
109 i : agent::asan::ASAN_READ_ACCESS);
110 : }
111 E : return ret;
112 E : }
113 :
114 E : const wchar_t* asan_wcschr(const wchar_t* str, wchar_t character) {
115 E : const wchar_t* s = str;
116 E : while (agent::asan::Shadow::IsAccessible(s) && *s != character && *s != NULL)
117 E : s++;
118 E : if (!agent::asan::Shadow::IsAccessible(s)) {
119 : ReportBadAccess(reinterpret_cast<const uint8*>(s),
120 E : agent::asan::ASAN_READ_ACCESS);
121 E : return ::wcschr(str, character);
122 :
123 : }
124 E : if (*s == NULL)
125 E : return NULL;
126 E : return s;
127 E : }
128 :
129 i : int __cdecl asan_strcmp(const char* str1, const char* str2) {
130 : // TODO(sebmarchand): Provide an implementation that guarantees the same
131 : // behavior as the original function.
132 i : NOTIMPLEMENTED();
133 i : return 0;
134 i : }
135 :
136 i : const char* __cdecl asan_strpbrk(const char* str1, const char* str2) {
137 : // TODO(sebmarchand): Provide an implementation that guarantees the same
138 : // behavior as the original function.
139 i : NOTIMPLEMENTED();
140 i : return NULL;
141 i : }
142 :
143 i : const char* __cdecl asan_strstr(const char* str1, const char* str2) {
144 : // TODO(sebmarchand): Provide an implementation that guarantees the same
145 : // behavior as the original function.
146 i : NOTIMPLEMENTED();
147 i : return NULL;
148 i : }
149 :
150 i : size_t __cdecl asan_strspn(const char* str1, const char* str2) {
151 : // TODO(sebmarchand): Provide an implementation that guarantees the same
152 : // behavior as the original function.
153 i : NOTIMPLEMENTED();
154 i : return 0;
155 i : }
156 :
157 E : char* __cdecl asan_strncpy(char* destination, const char* source, size_t num) {
158 E : if (num != 0U) {
159 E : size_t src_size = 0;
160 : if (!agent::asan::Shadow::GetNullTerminatedArraySize<char>(source,
161 : num,
162 : &src_size) &&
163 E : src_size <= num) {
164 : ReportBadAccess(reinterpret_cast<const uint8*>(source) + src_size,
165 E : agent::asan::ASAN_READ_ACCESS);
166 : }
167 : // We can't use the GetNullTerminatedArraySize function here, as destination
168 : // might not be null terminated.
169 : TestMemoryRange(reinterpret_cast<const uint8*>(destination),
170 : num,
171 E : agent::asan::ASAN_WRITE_ACCESS);
172 : }
173 E : return ::strncpy(destination, source, num);
174 E : }
175 :
176 E : char* __cdecl asan_strncat(char* destination, const char* source, size_t num) {
177 E : if (num != 0U) {
178 E : size_t src_size = 0;
179 : if (!agent::asan::Shadow::GetNullTerminatedArraySize<char>(source,
180 : num,
181 : &src_size) &&
182 E : src_size <= num) {
183 : ReportBadAccess(reinterpret_cast<const uint8*>(source) + src_size,
184 E : agent::asan::ASAN_READ_ACCESS);
185 : }
186 E : size_t dst_size = 0;
187 : if (!agent::asan::Shadow::GetNullTerminatedArraySize<char>(destination,
188 : 0U,
189 E : &dst_size)) {
190 : ReportBadAccess(reinterpret_cast<const uint8*>(destination) + dst_size,
191 E : agent::asan::ASAN_WRITE_ACCESS);
192 E : } else {
193 : // Test if we can append the source to the destination.
194 : TestMemoryRange(reinterpret_cast<const uint8*>(destination + dst_size),
195 : std::min(num, src_size),
196 E : agent::asan::ASAN_WRITE_ACCESS);
197 : }
198 : }
199 E : return ::strncat(destination, source, num);
200 E : }
201 :
202 : } // extern "C"
|