1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for sprintf
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <apitest.h>
9 #include <apitest_guard.h>
10 
11 #define WIN32_NO_STATUS
12 #include <stdio.h>
13 #include <tchar.h>
14 #include <pseh/pseh2.h>
15 #include <ndk/mmfuncs.h>
16 #include <ndk/rtlfuncs.h>
17 
18 #ifdef _MSC_VER
19 #pragma warning(disable:4778) // unterminated format string '%'
20 #elif defined(__GNUC__)
21 #pragma GCC diagnostic ignored "-Wformat"
22 #pragma GCC diagnostic ignored "-Wformat-zero-length"
23 #pragma GCC diagnostic ignored "-Wnonnull"
24 #if __GNUC__ >= 7
25 #pragma GCC diagnostic ignored "-Wformat-overflow"
26 #endif
27 #endif
28 
29 /* NOTE: This test is not only used for all the CRT apitests, but also for
30  *       user32's wsprintf. Make sure to test them all */
31 START_TEST(sprintf)
32 {
33     int Length;
34     CHAR Buffer[128];
35     PCHAR String;
36 
37     /* basic parameter tests */
38     StartSeh()
39         Length = sprintf(NULL, NULL);
40     EndSeh(STATUS_ACCESS_VIOLATION);
41 
42     StartSeh()
43         Length = sprintf(NULL, "");
44         ok_int(Length, 0);
45 #if TEST_CRTDLL || TEST_USER32
46     EndSeh(STATUS_ACCESS_VIOLATION);
47 #else
48     EndSeh(STATUS_SUCCESS);
49 #endif
50 
51     StartSeh()
52         Length = sprintf(NULL, "Hello");
53         ok_int(Length, 5);
54 #if TEST_CRTDLL || TEST_USER32
55     EndSeh(STATUS_ACCESS_VIOLATION);
56 #else
57     EndSeh(STATUS_SUCCESS);
58 #endif
59 
60     /* some basic formats */
61     Length = sprintf(Buffer, "abcde");
62     ok_str(Buffer, "abcde");
63     ok_int(Length, 5);
64 
65     Length = sprintf(Buffer, "%%");
66     ok_str(Buffer, "%");
67     ok_int(Length, 1);
68 
69     Length = sprintf(Buffer, "%");
70     ok_str(Buffer, "");
71     ok_int(Length, 0);
72 
73     Length = sprintf(Buffer, "%%%");
74     ok_str(Buffer, "%");
75     ok_int(Length, 1);
76 
77     Length = sprintf(Buffer, "%d", 8);
78     ok_str(Buffer, "8");
79     ok_int(Length, 1);
80 
81     Length = sprintf(Buffer, "%s", "hello");
82     ok_str(Buffer, "hello");
83     ok_int(Length, 5);
84 
85     /* field width for %s */
86     Length = sprintf(Buffer, "%8s", "hello");
87     ok_str(Buffer, "   hello");
88     ok_int(Length, 8);
89 
90     Length = sprintf(Buffer, "%4s", "hello");
91     ok_str(Buffer, "hello");
92     ok_int(Length, 5);
93 
94     Length = sprintf(Buffer, "%-8s", "hello");
95     ok_str(Buffer, "hello   ");
96     ok_int(Length, 8);
97 
98     Length = sprintf(Buffer, "%-5s", "hello");
99     ok_str(Buffer, "hello");
100     ok_int(Length, 5);
101 
102     Length = sprintf(Buffer, "%0s", "hello");
103     ok_str(Buffer, "hello");
104     ok_int(Length, 5);
105 
106     Length = sprintf(Buffer, "%-0s", "hello");
107     ok_str(Buffer, "hello");
108     ok_int(Length, 5);
109 
110     Length = sprintf(Buffer, "%*s", -8, "hello");
111 #ifdef TEST_USER32
112     ok_str(Buffer, "*s");
113     ok_int(Length, 2);
114 #else
115     ok_str(Buffer, "hello   ");
116     ok_int(Length, 8);
117 #endif
118 
119     /* precision for %s */
120     Length = sprintf(Buffer, "%.s", "hello");
121     ok_str(Buffer, "");
122     ok_int(Length, 0);
123 
124     Length = sprintf(Buffer, "%.0s", "hello");
125     ok_str(Buffer, "");
126     ok_int(Length, 0);
127 
128     Length = sprintf(Buffer, "%.10s", "hello");
129     ok_str(Buffer, "hello");
130     ok_int(Length, 5);
131 
132     Length = sprintf(Buffer, "%.5s", "hello");
133     ok_str(Buffer, "hello");
134     ok_int(Length, 5);
135 
136     Length = sprintf(Buffer, "%.4s", "hello");
137     ok_str(Buffer, "hell");
138     ok_int(Length, 4);
139 
140     StartSeh()
141         Length = sprintf(Buffer, "%.*s", -1, "hello");
142 #ifdef TEST_USER32
143         ok_str(Buffer, "*s");
144         ok_int(Length, 2);
145 #else
146         ok_str(Buffer, "hello");
147         ok_int(Length, 5);
148 #endif
149     EndSeh(STATUS_SUCCESS);
150 
151     String = AllocateGuarded(6);
152     if (!String)
153     {
154         skip("Guarded allocation failure\n");
155         return;
156     }
157 
158     strcpy(String, "hello");
159     StartSeh()
160         Length = sprintf(Buffer, "%.8s", String);
161         ok_str(Buffer, "hello");
162         ok_int(Length, 5);
163     EndSeh(STATUS_SUCCESS);
164 
165     StartSeh()
166         Length = sprintf(Buffer, "%.6s", String);
167         ok_str(Buffer, "hello");
168         ok_int(Length, 5);
169     EndSeh(STATUS_SUCCESS);
170 
171     StartSeh()
172         Length = sprintf(Buffer, "%.5s", String);
173         ok_str(Buffer, "hello");
174         ok_int(Length, 5);
175     EndSeh(STATUS_SUCCESS);
176 
177     StartSeh()
178         Length = sprintf(Buffer, "%.4s", String);
179         ok_str(Buffer, "hell");
180         ok_int(Length, 4);
181     EndSeh(STATUS_SUCCESS);
182 
183     String[5] = '!';
184     StartSeh()
185         Length = sprintf(Buffer, "%.5s", String);
186         ok_str(Buffer, "hello");
187         ok_int(Length, 5);
188 #ifdef TEST_USER32
189     EndSeh(STATUS_ACCESS_VIOLATION);
190 #else
191     EndSeh(STATUS_SUCCESS);
192 #endif
193 
194     StartSeh()
195         Length = sprintf(Buffer, "%.6s", String);
196         ok_str(Buffer, "hello!");
197         ok_int(Length, 6);
198 #ifdef TEST_USER32
199     EndSeh(STATUS_ACCESS_VIOLATION);
200 #else
201     EndSeh(STATUS_SUCCESS);
202 #endif
203 
204     StartSeh()
205         Length = sprintf(Buffer, "%.*s", 5, String);
206 #ifdef TEST_USER32
207         ok_str(Buffer, "*s");
208         ok_int(Length, 2);
209 #else
210         ok_str(Buffer, "hello");
211         ok_int(Length, 5);
212 #endif
213     EndSeh(STATUS_SUCCESS);
214 
215     StartSeh()
216         Length = sprintf(Buffer, "%.*s", 6, String);
217 #ifdef TEST_USER32
218         ok_str(Buffer, "*s");
219         ok_int(Length, 2);
220 #else
221         ok_str(Buffer, "hello!");
222         ok_int(Length, 6);
223 #endif
224     EndSeh(STATUS_SUCCESS);
225 
226     /* both field width and precision */
227     StartSeh()
228         Length = sprintf(Buffer, "%8.5s", String);
229         ok_str(Buffer, "   hello");
230         ok_int(Length, 8);
231 #ifdef TEST_USER32
232     EndSeh(STATUS_ACCESS_VIOLATION);
233 #else
234     EndSeh(STATUS_SUCCESS);
235 #endif
236 
237     StartSeh()
238         Length = sprintf(Buffer, "%-*.6s", -8, String);
239 #ifdef TEST_USER32
240         ok_str(Buffer, "*.6s");
241         ok_int(Length, 4);
242 #else
243         ok_str(Buffer, "hello!  ");
244         ok_int(Length, 8);
245 #endif
246     EndSeh(STATUS_SUCCESS);
247 
248     StartSeh()
249         Length = sprintf(Buffer, "%*.*s", -8, 6, String);
250 #ifdef TEST_USER32
251         ok_str(Buffer, "*.*s");
252         ok_int(Length, 4);
253 #else
254         ok_str(Buffer, "hello!  ");
255         ok_int(Length, 8);
256 #endif
257     EndSeh(STATUS_SUCCESS);
258 
259     FreeGuarded(String);
260 }
261