1 /*------------------------------------------------------------------
2  * wcscpy_s.c
3  *
4  * August 2014, D Wheeler
5  *
6  * Copyright (c) 2014 by Intel Corp
7  * All rights reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or
14  * sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  *------------------------------------------------------------------
30  */
31 
32 #include "safeclib_private.h"
33 #include "safe_str_constraint.h"
34 #include "safe_str_lib.h"
35 
36 
37 /**
38  * NAME
39  *    wcscpy_s
40  *
41  * SYNOPSIS
42  *    #include "safe_str_lib.h"
43  *    errno_t
44  *    wcscpy_s(wchar_t* dest, rsize_t dmax, const wchar_t* src)
45  *
46  * DESCRIPTION
47  *    The wcscpy_s function copies the wide character string pointed
48  *    to by src (including the terminating null character) into the
49  *    array pointed to by dest. All elements following the terminating
50  *    null character (if any) written by strcpy_s in the array of
51  *    dmax characters pointed to by dest are nulled when
52  *    wcscpy_s returns.
53  *
54  * SPECIFIED IN
55  *    ISO/IEC TR 24731, Programming languages, environments
56  *    and system software interfaces, Extensions to the C Library,
57  *    Part I: Bounds-checking interfaces
58  *
59  * INPUT PARAMETERS
60  *    dest      pointer to string that will be replaced by src.
61  *
62  *    dmax      restricted maximum length of dest
63  *
64  *    src       pointer to the wide character string that will be copied
65  *              to dest
66  *
67  * OUTPUT PARAMETERS
68  *    dest      updated
69  *
70  * RUNTIME CONSTRAINTS
71  *    Neither dest nor src shall be a null pointer.
72  *    dmax shall not be greater than RSIZE_MAX_STR.
73  *    dmax shall not equal zero.
74  *    dmax shall be greater than strnlen_s(src, dmax).
75  *    Copying shall not take place between objects that overlap.
76  *    If there is a runtime-constraint violation, then if dest
77  *       is not a null pointer and destmax is greater than zero and
78  *       not greater than RSIZE_MAX_STR, then strcpy_s nulls dest.
79  *
80  * RETURN VALUE
81  *    EOK        successful operation, the characters in src were
82  *               copied into dest and the result is null terminated.
83  *    ESNULLP    NULL pointer
84  *    ESZEROL    zero length
85  *    ESLEMAX    length exceeds max limit
86  *    ESOVRLP    strings overlap
87  *    ESNOSPC    not enough space to copy src
88  *
89  * ALSO SEE
90  *    strcpy_s, strcat_s(), strncat_s(), strncpy_s()
91  *    wcscat_s(),
92  *
93  */
94 errno_t
wcscpy_s(wchar_t * dest,rsize_t dmax,const wchar_t * src)95 wcscpy_s(wchar_t* dest, rsize_t dmax, const wchar_t* src)
96 {
97     rsize_t orig_dmax;
98     wchar_t *orig_dest;
99     const wchar_t *overlap_bumper;
100 
101     if (dest == NULL) {
102         invoke_safe_str_constraint_handler("wcscpy_s: dest is null",
103                    NULL, ESNULLP);
104         return RCNEGATE(ESNULLP);
105     }
106 
107     if (dmax == 0) {
108         invoke_safe_str_constraint_handler("wcscpy_s: dmax is 0",
109                    NULL, ESZEROL);
110         return RCNEGATE(ESZEROL);
111     }
112 
113     if (dmax*sizeof(wchar_t) > RSIZE_MAX_STR) {
114         invoke_safe_str_constraint_handler("wcscpy_s: dmax exceeds max",
115                    NULL, ESLEMAX);
116         return RCNEGATE(ESLEMAX);
117     }
118 
119     if (src == NULL) {
120 #ifdef SAFECLIB_STR_NULL_SLACK
121         /* null string to clear data */
122         while (dmax) {  *dest = '\0'; dmax--; dest++; }
123 #else
124         *dest = '\0';
125 #endif
126         invoke_safe_str_constraint_handler("wcscpy_s: src is null",
127                    NULL, ESNULLP);
128         return RCNEGATE(ESNULLP);
129     }
130 
131     /* Verify proper length according to dmax if src = dest */
132     if (dest == src) {
133     	/* Ensure that src is not longer than dmax */
134     	while (*src != L'\0' && (dmax != 0)) { src++; dmax--; }
135     	if ( *src != L'\0' ) {
136             invoke_safe_str_constraint_handler("wcscpy_s: src exceeds dmax",
137                        NULL, ESLEMAX);
138             return RCNEGATE(ESLEMAX);
139     	}
140         return RCNEGATE(EOK);
141     }
142 
143     /* hold base of dest in case src was not copied */
144     orig_dmax = dmax;
145     orig_dest = dest;
146 
147     if (dest < src) {
148         overlap_bumper = src;
149 
150         while (dmax > 0) {
151             if (dest == overlap_bumper) {
152                 handle_wc_error(orig_dest, orig_dmax, "wcscpy_s: "
153                              "overlapping objects",
154                              ESOVRLP);
155                 return RCNEGATE(ESOVRLP);
156             }
157 
158             *dest = *src;
159             if (*dest == '\0') {
160 #ifdef SAFECLIB_STR_NULL_SLACK
161                 /* null slack to clear any data */
162                 while (dmax) { *dest = '\0'; dmax--; dest++; }
163 #endif
164                 return RCNEGATE(EOK);
165             }
166 
167             dmax--;
168             dest++;
169             src++;
170         }
171 
172     } else {
173         overlap_bumper = dest;
174 
175         while (dmax > 0) {
176             if (src == overlap_bumper) {
177                 handle_wc_error(orig_dest, orig_dmax, "wcscpy_s: "
178                       "overlapping objects",
179                       ESOVRLP);
180                 return RCNEGATE(ESOVRLP);
181             }
182 
183             *dest = *src;
184             if (*dest == '\0') {
185 #ifdef SAFECLIB_STR_NULL_SLACK
186                 /* null slack to clear any data */
187                 while (dmax) { *dest = '\0'; dmax--; dest++; }
188 #endif
189                 return RCNEGATE(EOK);
190             }
191 
192             dmax--;
193             dest++;
194             src++;
195         }
196     }
197 
198     /*
199      * the entire src must have been copied, if not reset dest
200      * to null the string.
201      */
202     handle_wc_error(orig_dest, orig_dmax, "wcscpy_s: not "
203                  "enough space for src",
204                  ESNOSPC);
205     return RCNEGATE(ESNOSPC);
206 }
207 EXPORT_SYMBOL(wcscpy_s)
208