1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*** |
6 | *sscanf_s.c - read formatted data from string |
7 | * |
8 | |
9 | * |
10 | *Purpose: |
11 | * defines scanf() - reads formatted data from string |
12 | * |
13 | *******************************************************************************/ |
14 | |
15 | #include <string.h> |
16 | #include <errno.h> |
17 | #include <limits.h> |
18 | #include "internal_securecrt.h" |
19 | |
20 | #include "mbusafecrt_internal.h" |
21 | |
22 | typedef int (*INPUTFN)(miniFILE *, const unsigned char*, va_list); |
23 | typedef int (*WINPUTFN)(miniFILE *, const wchar_t*, va_list); |
24 | extern size_t PAL_wcsnlen(const WCHAR* inString, size_t inMaxSize); |
25 | |
26 | /*** |
27 | *static int v[nw]scan_fn([w]inputfn, string, [count], format, ...) |
28 | * |
29 | *Purpose: |
30 | * this is a helper function which is called by the other functions |
31 | * in this file - sscanf/swscanf/snscanf etc. It calls either _(w)input or |
32 | * _(w)input_s depending on the first parameter. |
33 | * |
34 | *******************************************************************************/ |
35 | |
36 | static int __cdecl vscan_fn ( |
37 | INPUTFN inputfn, |
38 | const char *string, |
39 | const char *format, |
40 | va_list arglist |
41 | ) |
42 | { |
43 | miniFILE str; |
44 | miniFILE *infile = &str; |
45 | int retval; |
46 | size_t count = strlen(string); |
47 | |
48 | _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); |
49 | _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); |
50 | |
51 | infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; |
52 | infile->_ptr = infile->_base = (char *) string; |
53 | |
54 | if(count>(INT_MAX/sizeof(char))) |
55 | { |
56 | /* old-style functions allow any large value to mean unbounded */ |
57 | infile->_cnt = INT_MAX; |
58 | } |
59 | else |
60 | { |
61 | infile->_cnt = (int)count*sizeof(char); |
62 | } |
63 | |
64 | retval = (inputfn(infile, ( const unsigned char* )format, arglist)); |
65 | |
66 | return(retval); |
67 | } |
68 | |
69 | static int __cdecl vnscan_fn ( |
70 | INPUTFN inputfn, |
71 | const char *string, |
72 | size_t count, |
73 | const char *format, |
74 | va_list arglist |
75 | ) |
76 | { |
77 | miniFILE str; |
78 | miniFILE *infile = &str; |
79 | int retval; |
80 | size_t length = strlen(string); |
81 | |
82 | _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); |
83 | _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); |
84 | |
85 | infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; |
86 | infile->_ptr = infile->_base = (char *) string; |
87 | |
88 | if ( count > length ) |
89 | { |
90 | count = length; |
91 | } |
92 | |
93 | if(count>(INT_MAX/sizeof(char))) |
94 | { |
95 | /* old-style functions allow any large value to mean unbounded */ |
96 | infile->_cnt = INT_MAX; |
97 | } |
98 | else |
99 | { |
100 | infile->_cnt = (int)count*sizeof(char); |
101 | } |
102 | |
103 | retval = (inputfn(infile, ( const unsigned char* )format, arglist)); |
104 | |
105 | return(retval); |
106 | } |
107 | |
108 | static int __cdecl vwscan_fn ( |
109 | WINPUTFN inputfn, |
110 | const wchar_t *string, |
111 | const wchar_t *format, |
112 | va_list arglist |
113 | ) |
114 | { |
115 | miniFILE str; |
116 | miniFILE *infile = &str; |
117 | int retval; |
118 | size_t count = PAL_wcsnlen(string, INT_MAX); |
119 | |
120 | _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); |
121 | _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); |
122 | |
123 | infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; |
124 | infile->_ptr = infile->_base = (char *) string; |
125 | |
126 | if(count>(INT_MAX/sizeof(wchar_t))) |
127 | { |
128 | /* old-style functions allow any large value to mean unbounded */ |
129 | infile->_cnt = INT_MAX; |
130 | } |
131 | else |
132 | { |
133 | infile->_cnt = (int)count*sizeof(wchar_t); |
134 | } |
135 | |
136 | retval = (inputfn(infile, format, arglist)); |
137 | |
138 | return(retval); |
139 | } |
140 | |
141 | static int __cdecl vnwscan_fn ( |
142 | WINPUTFN inputfn, |
143 | const wchar_t *string, |
144 | size_t count, |
145 | const wchar_t *format, |
146 | va_list arglist |
147 | ) |
148 | { |
149 | miniFILE str; |
150 | miniFILE *infile = &str; |
151 | int retval; |
152 | size_t length = PAL_wcsnlen(string, INT_MAX); |
153 | |
154 | _VALIDATE_RETURN( (string != NULL), EINVAL, EOF); |
155 | _VALIDATE_RETURN( (format != NULL), EINVAL, EOF); |
156 | |
157 | infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF; |
158 | infile->_ptr = infile->_base = (char *) string; |
159 | |
160 | if ( count > length ) |
161 | { |
162 | count = length; |
163 | } |
164 | |
165 | if(count>(INT_MAX/sizeof(wchar_t))) |
166 | { |
167 | /* old-style functions allow any large value to mean unbounded */ |
168 | infile->_cnt = INT_MAX; |
169 | } |
170 | else |
171 | { |
172 | infile->_cnt = (int)count*sizeof(wchar_t); |
173 | } |
174 | |
175 | retval = (inputfn(infile, format, arglist)); |
176 | |
177 | return(retval); |
178 | } |
179 | |
180 | |
181 | /*** |
182 | *int sscanf_s(string, format, ...) |
183 | * Same as sscanf above except that it calls _input_s to do the real work. |
184 | * |
185 | *int snscanf_s(string, size, format, ...) |
186 | * Same as snscanf above except that it calls _input_s to do the real work. |
187 | * |
188 | * _input_s has a size check for array parameters. |
189 | * |
190 | *******************************************************************************/ |
191 | |
192 | int __cdecl sscanf_s ( |
193 | const char *string, |
194 | const char *format, |
195 | ... |
196 | ) |
197 | { |
198 | int ret; |
199 | va_list arglist; |
200 | va_start(arglist, format); |
201 | ret = vscan_fn(__tinput_s, string, format, arglist); |
202 | va_end(arglist); |
203 | return ret; |
204 | } |
205 | |
206 | int __cdecl _snscanf_s ( |
207 | const char *string, |
208 | size_t count, |
209 | const char *format, |
210 | ... |
211 | ) |
212 | { |
213 | int ret; |
214 | va_list arglist; |
215 | va_start(arglist, format); |
216 | ret = vnscan_fn(__tinput_s, string, count, format, arglist); |
217 | va_end(arglist); |
218 | return ret; |
219 | } |
220 | |
221 | int __cdecl swscanf_s ( |
222 | const wchar_t *string, |
223 | const wchar_t *format, |
224 | ... |
225 | ) |
226 | { |
227 | int ret; |
228 | va_list arglist; |
229 | va_start(arglist, format); |
230 | ret = vwscan_fn(__twinput_s, string, format, arglist); |
231 | va_end(arglist); |
232 | return ret; |
233 | } |
234 | |
235 | int __cdecl _snwscanf_s ( |
236 | const wchar_t *string, |
237 | size_t count, |
238 | const wchar_t *format, |
239 | ... |
240 | ) |
241 | { |
242 | int ret; |
243 | va_list arglist; |
244 | va_start(arglist, format); |
245 | ret = vnwscan_fn(__twinput_s, string, count, format, arglist); |
246 | va_end(arglist); |
247 | return ret; |
248 | } |
249 | |
250 | |