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
22typedef int (*INPUTFN)(miniFILE *, const unsigned char*, va_list);
23typedef int (*WINPUTFN)(miniFILE *, const wchar_t*, va_list);
24extern 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
36static 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
69static 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
108static 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
141static 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
192int __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
206int __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
221int __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
235int __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