b612d6d993fcbe0fc9296bb7384d02ce4d15a769
[reactos.git] / modules / rostests / apitests / crt / sprintf.c
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
10 #define WIN32_NO_STATUS
11 #include <stdio.h>
12 #include <tchar.h>
13 #include <pseh/pseh2.h>
14 #include <ndk/mmfuncs.h>
15 #include <ndk/rtlfuncs.h>
16
17 #ifdef _MSC_VER
18 #pragma warning(disable:4778) // unterminated format string '%'
19 #elif defined(__GNUC__)
20 #pragma GCC diagnostic ignored "-Wformat"
21 #pragma GCC diagnostic ignored "-Wformat-zero-length"
22 #pragma GCC diagnostic ignored "-Wnonnull"
23 #if __GNUC__ >= 7
24 #pragma GCC diagnostic ignored "-Wformat-overflow"
25 #endif
26 #endif
27
28 static
29 PVOID
30 AllocateGuarded(
31 SIZE_T SizeRequested)
32 {
33 NTSTATUS Status;
34 SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
35 PVOID VirtualMemory = NULL;
36 PCHAR StartOfBuffer;
37
38 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
39
40 if (!NT_SUCCESS(Status))
41 return NULL;
42
43 Size -= PAGE_SIZE;
44 if (Size)
45 {
46 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
47 if (!NT_SUCCESS(Status))
48 {
49 Size = 0;
50 Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
51 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
52 return NULL;
53 }
54 }
55
56 StartOfBuffer = VirtualMemory;
57 StartOfBuffer += Size - SizeRequested;
58
59 return StartOfBuffer;
60 }
61
62 static
63 VOID
64 FreeGuarded(
65 PVOID Pointer)
66 {
67 NTSTATUS Status;
68 PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
69 SIZE_T Size = 0;
70
71 Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
72 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
73 }
74
75 /* NOTE: This test is not only used for all the CRT apitests, but also for
76 * user32's wsprintf. Make sure to test them all */
77 START_TEST(sprintf)
78 {
79 int Length;
80 CHAR Buffer[128];
81 PCHAR String;
82
83 /* basic parameter tests */
84 StartSeh()
85 Length = sprintf(NULL, NULL);
86 EndSeh(STATUS_ACCESS_VIOLATION);
87
88 StartSeh()
89 Length = sprintf(NULL, "");
90 ok_int(Length, 0);
91 #if TEST_CRTDLL || TEST_USER32
92 EndSeh(STATUS_ACCESS_VIOLATION);
93 #else
94 EndSeh(STATUS_SUCCESS);
95 #endif
96
97 StartSeh()
98 Length = sprintf(NULL, "Hello");
99 ok_int(Length, 5);
100 #if TEST_CRTDLL || TEST_USER32
101 EndSeh(STATUS_ACCESS_VIOLATION);
102 #else
103 EndSeh(STATUS_SUCCESS);
104 #endif
105
106 /* some basic formats */
107 Length = sprintf(Buffer, "abcde");
108 ok_str(Buffer, "abcde");
109 ok_int(Length, 5);
110
111 Length = sprintf(Buffer, "%%");
112 ok_str(Buffer, "%");
113 ok_int(Length, 1);
114
115 Length = sprintf(Buffer, "%");
116 ok_str(Buffer, "");
117 ok_int(Length, 0);
118
119 Length = sprintf(Buffer, "%%%");
120 ok_str(Buffer, "%");
121 ok_int(Length, 1);
122
123 Length = sprintf(Buffer, "%d", 8);
124 ok_str(Buffer, "8");
125 ok_int(Length, 1);
126
127 Length = sprintf(Buffer, "%s", "hello");
128 ok_str(Buffer, "hello");
129 ok_int(Length, 5);
130
131 /* field width for %s */
132 Length = sprintf(Buffer, "%8s", "hello");
133 ok_str(Buffer, " hello");
134 ok_int(Length, 8);
135
136 Length = sprintf(Buffer, "%4s", "hello");
137 ok_str(Buffer, "hello");
138 ok_int(Length, 5);
139
140 Length = sprintf(Buffer, "%-8s", "hello");
141 ok_str(Buffer, "hello ");
142 ok_int(Length, 8);
143
144 Length = sprintf(Buffer, "%-5s", "hello");
145 ok_str(Buffer, "hello");
146 ok_int(Length, 5);
147
148 Length = sprintf(Buffer, "%0s", "hello");
149 ok_str(Buffer, "hello");
150 ok_int(Length, 5);
151
152 Length = sprintf(Buffer, "%-0s", "hello");
153 ok_str(Buffer, "hello");
154 ok_int(Length, 5);
155
156 Length = sprintf(Buffer, "%*s", -8, "hello");
157 #ifdef TEST_USER32
158 ok_str(Buffer, "*s");
159 ok_int(Length, 2);
160 #else
161 ok_str(Buffer, "hello ");
162 ok_int(Length, 8);
163 #endif
164
165 /* precision for %s */
166 Length = sprintf(Buffer, "%.s", "hello");
167 ok_str(Buffer, "");
168 ok_int(Length, 0);
169
170 Length = sprintf(Buffer, "%.0s", "hello");
171 ok_str(Buffer, "");
172 ok_int(Length, 0);
173
174 Length = sprintf(Buffer, "%.10s", "hello");
175 ok_str(Buffer, "hello");
176 ok_int(Length, 5);
177
178 Length = sprintf(Buffer, "%.5s", "hello");
179 ok_str(Buffer, "hello");
180 ok_int(Length, 5);
181
182 Length = sprintf(Buffer, "%.4s", "hello");
183 ok_str(Buffer, "hell");
184 ok_int(Length, 4);
185
186 StartSeh()
187 Length = sprintf(Buffer, "%.*s", -1, "hello");
188 #ifdef TEST_USER32
189 ok_str(Buffer, "*s");
190 ok_int(Length, 2);
191 #else
192 ok_str(Buffer, "hello");
193 ok_int(Length, 5);
194 #endif
195 EndSeh(STATUS_SUCCESS);
196
197 String = AllocateGuarded(6);
198 if (!String)
199 {
200 skip("Guarded allocation failure\n");
201 return;
202 }
203
204 strcpy(String, "hello");
205 StartSeh()
206 Length = sprintf(Buffer, "%.8s", String);
207 ok_str(Buffer, "hello");
208 ok_int(Length, 5);
209 EndSeh(STATUS_SUCCESS);
210
211 StartSeh()
212 Length = sprintf(Buffer, "%.6s", String);
213 ok_str(Buffer, "hello");
214 ok_int(Length, 5);
215 EndSeh(STATUS_SUCCESS);
216
217 StartSeh()
218 Length = sprintf(Buffer, "%.5s", String);
219 ok_str(Buffer, "hello");
220 ok_int(Length, 5);
221 EndSeh(STATUS_SUCCESS);
222
223 StartSeh()
224 Length = sprintf(Buffer, "%.4s", String);
225 ok_str(Buffer, "hell");
226 ok_int(Length, 4);
227 EndSeh(STATUS_SUCCESS);
228
229 String[5] = '!';
230 StartSeh()
231 Length = sprintf(Buffer, "%.5s", String);
232 ok_str(Buffer, "hello");
233 ok_int(Length, 5);
234 #ifdef TEST_USER32
235 EndSeh(STATUS_ACCESS_VIOLATION);
236 #else
237 EndSeh(STATUS_SUCCESS);
238 #endif
239
240 StartSeh()
241 Length = sprintf(Buffer, "%.6s", String);
242 ok_str(Buffer, "hello!");
243 ok_int(Length, 6);
244 #ifdef TEST_USER32
245 EndSeh(STATUS_ACCESS_VIOLATION);
246 #else
247 EndSeh(STATUS_SUCCESS);
248 #endif
249
250 StartSeh()
251 Length = sprintf(Buffer, "%.*s", 5, String);
252 #ifdef TEST_USER32
253 ok_str(Buffer, "*s");
254 ok_int(Length, 2);
255 #else
256 ok_str(Buffer, "hello");
257 ok_int(Length, 5);
258 #endif
259 EndSeh(STATUS_SUCCESS);
260
261 StartSeh()
262 Length = sprintf(Buffer, "%.*s", 6, String);
263 #ifdef TEST_USER32
264 ok_str(Buffer, "*s");
265 ok_int(Length, 2);
266 #else
267 ok_str(Buffer, "hello!");
268 ok_int(Length, 6);
269 #endif
270 EndSeh(STATUS_SUCCESS);
271
272 /* both field width and precision */
273 StartSeh()
274 Length = sprintf(Buffer, "%8.5s", String);
275 ok_str(Buffer, " hello");
276 ok_int(Length, 8);
277 #ifdef TEST_USER32
278 EndSeh(STATUS_ACCESS_VIOLATION);
279 #else
280 EndSeh(STATUS_SUCCESS);
281 #endif
282
283 StartSeh()
284 Length = sprintf(Buffer, "%-*.6s", -8, String);
285 #ifdef TEST_USER32
286 ok_str(Buffer, "*.6s");
287 ok_int(Length, 4);
288 #else
289 ok_str(Buffer, "hello! ");
290 ok_int(Length, 8);
291 #endif
292 EndSeh(STATUS_SUCCESS);
293
294 StartSeh()
295 Length = sprintf(Buffer, "%*.*s", -8, 6, String);
296 #ifdef TEST_USER32
297 ok_str(Buffer, "*.*s");
298 ok_int(Length, 4);
299 #else
300 ok_str(Buffer, "hello! ");
301 ok_int(Length, 8);
302 #endif
303 EndSeh(STATUS_SUCCESS);
304
305 FreeGuarded(String);
306 }