1 /*------------------------------------------------------------------
2 * strncpy_s.c / strcpy_s.c / strnlen_s.c
3 *
4 * October 2008, Bo Berry
5 *
6 * Copyright � 2008-2011 by Cisco Systems, Inc
7 * All rights reserved.
8 
9 * safe_str_constraint.c
10 *
11 =============================
12 Safe String Library license:
13 =============================
14 MIT License
15 
16 Copyright (c) 2014-2018 Intel Corporation
17 
18 Permission is hereby granted, free of charge, to any person obtaining a copy
19 of this software and associated documentation files (the "Software"), to deal
20 in the Software without restriction, including without limitation the rights
21 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 copies of the Software, and to permit persons to whom the Software is
23 furnished to do so, subject to the following conditions:
24 
25 The above copyright notice and this permission notice shall be included in all
26 copies or substantial portions of the Software.
27 
28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 SOFTWARE.
35 
36 ================================================================================
37 
38 Copyright (C) 2012, 2013 Cisco Systems
39 All rights reserved.
40 
41 Permission is hereby granted, free of charge, to any person
42 obtaining a copy of this software and associated documentation
43 files (the "Software"), to deal in the Software without
44 restriction, including without limitation the rights to use,
45 copy, modify, merge, publish, distribute, sublicense, and/or
46 sell copies of the Software, and to permit persons to whom the
47 Software is furnished to do so, subject to the following
48 conditions:
49 
50 The above copyright notice and this permission notice shall be
51 included in all copies or substantial portions of the Software.
52 
53 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
54 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
55 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
56 NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
57 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
58 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
59 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
60 OTHER DEALINGS IN THE SOFTWARE.
61 */
62 #include "EbString.h"
63 
64 /* SAFE STRING LIBRARY */
65 
66 static constraint_handler_t str_handler = NULL;
67 
68 void
EbHevcInvoke_safe_str_constraint_handler(const char * msg,void * ptr,errno_t error)69 EbHevcInvoke_safe_str_constraint_handler(const char *msg,
70 void *ptr,
71 errno_t error)
72 {
73     if (NULL != str_handler)
74         str_handler(msg, ptr, error);
75     else
76         sl_default_handler(msg, ptr, error);
77 }
78 
EbHevcIgnore_handler_s(const char * msg,void * ptr,errno_t error)79 void EbHevcIgnore_handler_s(const char *msg, void *ptr, errno_t error)
80 {
81     (void)msg;
82     (void)ptr;
83     (void)error;
84     sldebug_printf("IGNORE CONSTRAINT HANDLER: (%u) %s\n", error,
85         (msg) ? msg : "Null message");
86     return;
87 }
88 
89 errno_t
EbHevcStrncpy_ss(char * dest,rsize_t dmax,const char * src,rsize_t slen)90 EbHevcStrncpy_ss(char *dest, rsize_t dmax, const char *src, rsize_t slen)
91 {
92     rsize_t orig_dmax;
93     char *orig_dest;
94     const char *overlap_bumper;
95 
96     if (dest == NULL) {
97         EbHevcInvoke_safe_str_constraint_handler("strncpy_ss: dest is null",
98             NULL, ESNULLP);
99         return RCNEGATE(ESNULLP);
100     }
101 
102     if (dmax == 0) {
103         EbHevcInvoke_safe_str_constraint_handler("strncpy_ss: dmax is 0",
104             NULL, ESZEROL);
105         return RCNEGATE(ESZEROL);
106     }
107 
108     if (dmax > RSIZE_MAX_STR) {
109         EbHevcInvoke_safe_str_constraint_handler("strncpy_ss: dmax exceeds max",
110             NULL, ESLEMAX);
111         return RCNEGATE(ESLEMAX);
112     }
113 
114     /* hold base in case src was not copied */
115     orig_dmax = dmax;
116     orig_dest = dest;
117 
118     if (src == NULL) {
119         EbHevcHandle_error(orig_dest, orig_dmax, (char*) ("strncpy_ss: "
120             "src is null"),
121             ESNULLP);
122         return RCNEGATE(ESNULLP);
123     }
124 
125     if (slen == 0) {
126         EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strncpy_ss: "
127             "slen is zero"),
128             ESZEROL);
129         return RCNEGATE(ESZEROL);
130     }
131 
132     if (slen > RSIZE_MAX_STR) {
133         EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strncpy_ss: "
134             "slen exceeds max"),
135             ESLEMAX);
136         return RCNEGATE(ESLEMAX);
137     }
138 
139     if (dest < src) {
140         overlap_bumper = src;
141 
142         while (dmax > 0) {
143             if (dest == overlap_bumper) {
144                 EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strncpy_ss: "
145                     "overlapping objects"),
146                     ESOVRLP);
147                 return RCNEGATE(ESOVRLP);
148             }
149 
150             if (slen == 0) {
151                 /*
152                 * Copying truncated to slen chars.  Note that the TR says to
153                 * copy slen chars plus the null char.  We null the slack.
154                 */
155                 *dest = '\0';
156                 return RCNEGATE(EOK);
157             }
158 
159             *dest = *src;
160             if (*dest == '\0')
161                 return RCNEGATE(EOK);
162             dmax--;
163             slen--;
164             dest++;
165             src++;
166         }
167     }
168     else {
169         overlap_bumper = dest;
170 
171         while (dmax > 0) {
172             if (src == overlap_bumper) {
173                 EbHevcHandle_error(orig_dest, orig_dmax, (char*)( "strncpy_s: "
174                     "overlapping objects"),
175                     ESOVRLP);
176                 return RCNEGATE(ESOVRLP);
177             }
178 
179             if (slen == 0) {
180                 /*
181                 * Copying truncated to slen chars.  Note that the TR says to
182                 * copy slen chars plus the null char.  We null the slack.
183                 */
184                 *dest = '\0';
185                 return RCNEGATE(EOK);
186             }
187 
188             *dest = *src;
189             if (*dest == '\0')
190                 return RCNEGATE(EOK);
191             dmax--;
192             slen--;
193             dest++;
194             src++;
195         }
196     }
197 
198     /*
199     * the entire src was not copied, so zero the string
200     */
201     EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strncpy_ss: not enough "
202         "space for src"),
203         ESNOSPC);
204     return RCNEGATE(ESNOSPC);
205 }
206 
207 errno_t
EbHevcStrcpy_ss(char * dest,rsize_t dmax,const char * src)208 EbHevcStrcpy_ss(char *dest, rsize_t dmax, const char *src)
209 {
210     rsize_t orig_dmax;
211     char *orig_dest;
212     const char *overlap_bumper;
213 
214     if (dest == NULL) {
215         EbHevcInvoke_safe_str_constraint_handler((char*)("strcpy_ss: dest is null"),
216             NULL, ESNULLP);
217         return RCNEGATE(ESNULLP);
218     }
219 
220     if (dmax == 0) {
221         EbHevcInvoke_safe_str_constraint_handler((char*)("strcpy_ss: dmax is 0"),
222             NULL, ESZEROL);
223         return RCNEGATE(ESZEROL);
224     }
225 
226     if (dmax > RSIZE_MAX_STR) {
227         EbHevcInvoke_safe_str_constraint_handler((char*)("strcpy_ss: dmax exceeds max"),
228             NULL, ESLEMAX);
229         return RCNEGATE(ESLEMAX);
230     }
231 
232     if (src == NULL) {
233         *dest = '\0';
234         EbHevcInvoke_safe_str_constraint_handler((char*)("strcpy_ss: src is null"),
235             NULL, ESNULLP);
236         return RCNEGATE(ESNULLP);
237     }
238 
239     if (dest == src)
240         return RCNEGATE(EOK);
241     /* hold base of dest in case src was not copied */
242     orig_dmax = dmax;
243     orig_dest = dest;
244 
245     if (dest < src) {
246         overlap_bumper = src;
247 
248         while (dmax > 0) {
249             if (dest == overlap_bumper) {
250                 EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strcpy_ss: "
251                     "overlapping objects"),
252                     ESOVRLP);
253                 return RCNEGATE(ESOVRLP);
254             }
255 
256             *dest = *src;
257             if (*dest == '\0')
258                 return RCNEGATE(EOK);
259             dmax--;
260             dest++;
261             src++;
262         }
263     }
264     else {
265         overlap_bumper = dest;
266 
267         while (dmax > 0) {
268             if (src == overlap_bumper) {
269                 EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strcpy_ss: "
270                     "overlapping objects"),
271                     ESOVRLP);
272                 return RCNEGATE(ESOVRLP);
273             }
274 
275             *dest = *src;
276             if (*dest == '\0')
277                 return RCNEGATE(EOK);
278             dmax--;
279             dest++;
280             src++;
281         }
282     }
283 
284     /*
285     * the entire src must have been copied, if not reset dest
286     * to null the string.
287     */
288     EbHevcHandle_error(orig_dest, orig_dmax, (char*)("strcpy_ss: not "
289         "enough space for src"),
290         ESNOSPC);
291     return RCNEGATE(ESNOSPC);
292 }
293 
294 rsize_t
EbHevcStrnlen_ss(const char * dest,rsize_t dmax)295 EbHevcStrnlen_ss(const char *dest, rsize_t dmax)
296 {
297     rsize_t count;
298 
299     if (dest == NULL)
300         return RCNEGATE(0);
301     if (dmax == 0) {
302         EbHevcInvoke_safe_str_constraint_handler((char*)("strnlen_ss: dmax is 0"),
303             NULL, ESZEROL);
304         return RCNEGATE(0);
305     }
306 
307     if (dmax > RSIZE_MAX_STR) {
308         EbHevcInvoke_safe_str_constraint_handler((char*)("strnlen_ss: dmax exceeds max"),
309             NULL, ESLEMAX);
310         return RCNEGATE(0);
311     }
312 
313     count = 0;
314     while (*dest && dmax) {
315         count++;
316         dmax--;
317         dest++;
318     }
319 
320     return RCNEGATE(count);
321 }
322 
323 /* SAFE STRING LIBRARY */
324