forked from openenclave/openenclave
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsafecrt.c
216 lines (180 loc) · 4.62 KB
/
safecrt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// Copyright (c) Open Enclave SDK contributors.
// Licensed under the MIT License.
#include <openenclave/internal/raise.h>
#include <openenclave/internal/safecrt.h>
#include "common.h"
oe_result_t oe_memcpy_s(
void* dst,
size_t dst_size,
const void* src,
size_t num_bytes)
{
oe_result_t result = OE_FAILURE;
if (dst == NULL)
OE_RAISE(OE_INVALID_PARAMETER);
if (src == NULL || dst_size < num_bytes)
{
memset(dst, 0, dst_size);
OE_RAISE(OE_INVALID_PARAMETER);
}
/* Reject overlapping buffers. */
if ((dst >= src && ((uint8_t*)dst < (uint8_t*)src + num_bytes)) ||
(dst < src && ((uint8_t*)dst + dst_size > (uint8_t*)src)))
{
memset(dst, 0, dst_size);
OE_RAISE(OE_OVERLAPPED_COPY);
}
memcpy(dst, src, num_bytes);
result = OE_OK;
done:
return result;
}
oe_result_t oe_memmove_s(
void* dst,
size_t dst_size,
const void* src,
size_t num_bytes)
{
oe_result_t result = OE_FAILURE;
if (dst == NULL)
OE_RAISE(OE_INVALID_PARAMETER);
if (src == NULL || dst_size < num_bytes)
{
memset(dst, 0, dst_size);
OE_RAISE(OE_INVALID_PARAMETER);
}
memmove(dst, src, num_bytes);
result = OE_OK;
done:
return result;
}
oe_result_t oe_memset_s(void* dst, size_t dst_size, int value, size_t num_bytes)
{
oe_result_t result = OE_FAILURE;
volatile unsigned char* p = dst;
if (dst == NULL)
OE_RAISE(OE_INVALID_PARAMETER);
/* The C11 standard states that memset_s will store `value` in
* `dst[0...dst_size]` even during a runtime violation. */
if (dst_size < num_bytes)
{
result = OE_INVALID_PARAMETER;
num_bytes = dst_size;
}
else
{
result = OE_OK;
}
/* memset_s cannot be optimized away by the compiler */
while (num_bytes--)
*p++ = (unsigned char)value;
done:
return result;
}
OE_INLINE oe_result_t _oe_validate_string(char* str, size_t size)
{
if (str != NULL && size > 0)
return OE_OK;
return OE_INVALID_PARAMETER;
}
OE_INLINE void _oe_fill_string(char* str, size_t size)
{
OE_UNUSED(str);
OE_UNUSED(size);
#ifndef NDEBUG
// Fill memory with pattern.
memset(str, 0xFD, size);
#endif
}
OE_INLINE void _oe_reset_string(char* str, size_t size)
{
*str = '\0';
_oe_fill_string(str + 1, size - 1);
}
oe_result_t oe_strncat_s(
char* dst,
size_t dst_size,
const char* src,
size_t num_bytes)
{
oe_result_t result = OE_FAILURE;
char* p = dst;
size_t available = dst_size;
/* Reject invalid parameters. */
OE_CHECK(_oe_validate_string(dst, dst_size));
if (src == NULL)
{
_oe_reset_string(dst, dst_size);
OE_RAISE(OE_INVALID_PARAMETER);
}
while (available > 0 && *p != 0)
{
if (p == src)
{
_oe_reset_string(dst, dst_size);
OE_RAISE(OE_OVERLAPPED_COPY);
}
p++;
available--;
}
/* Not null terimated. */
if (available == 0)
{
_oe_reset_string(dst, dst_size);
OE_RAISE(OE_BUFFER_TOO_SMALL);
}
/* Copy from the end of the destination string. */
result = oe_strncpy_s(p, available, src, num_bytes);
if (result != OE_OK)
{
_oe_reset_string(dst, dst_size);
OE_RAISE(result);
}
result = OE_OK;
done:
return result;
}
oe_result_t oe_strncpy_s(
char* dst,
size_t dst_size,
const char* src,
size_t num_bytes)
{
oe_result_t result = OE_FAILURE;
const char* current_src = src;
char* current_dst = dst;
size_t current_dst_size = dst_size;
/* Reject invalid parameters. */
OE_CHECK(_oe_validate_string(dst, dst_size));
if (src == NULL)
{
_oe_reset_string(dst, dst_size);
OE_RAISE(OE_INVALID_PARAMETER);
}
/* Copy until we hit one of the terminating conditions. */
while (current_dst_size != 0)
{
/* If we detect an overlapped copy, we will return an error. */
if (current_dst == src || current_src == dst)
{
_oe_reset_string(dst, dst_size);
OE_RAISE(OE_OVERLAPPED_COPY);
}
/* Successful terminating conditions for strncpy_s. */
if (num_bytes == 0 || *current_src == '\0')
{
*current_dst = '\0';
result = OE_OK;
goto done;
}
/* Copy and contine looping. */
*current_dst++ = *current_src++;
current_dst_size--;
num_bytes--;
}
/* Destination buffer is not large enough. */
_oe_reset_string(dst, dst_size);
OE_RAISE(OE_BUFFER_TOO_SMALL);
done:
return result;
}