t_snprintb.c revision 1.20 1 1.20 rillig /* $NetBSD: t_snprintb.c,v 1.20 2024/02/16 19:53:40 rillig Exp $ */
2 1.1 jmmv
3 1.1 jmmv /*
4 1.9 rillig * Copyright (c) 2002, 2004, 2008, 2010, 2024 The NetBSD Foundation, Inc.
5 1.1 jmmv * All rights reserved.
6 1.1 jmmv *
7 1.9 rillig * This code was contributed to The NetBSD Foundation by Christos Zoulas and
8 1.9 rillig * Roland Illig.
9 1.1 jmmv *
10 1.1 jmmv * Redistribution and use in source and binary forms, with or without
11 1.1 jmmv * modification, are permitted provided that the following conditions
12 1.1 jmmv * are met:
13 1.1 jmmv * 1. Redistributions of source code must retain the above copyright
14 1.1 jmmv * notice, this list of conditions and the following disclaimer.
15 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 jmmv * notice, this list of conditions and the following disclaimer in the
17 1.1 jmmv * documentation and/or other materials provided with the distribution.
18 1.1 jmmv *
19 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 jmmv * POSSIBILITY OF SUCH DAMAGE.
30 1.1 jmmv */
31 1.1 jmmv
32 1.1 jmmv #include <sys/cdefs.h>
33 1.1 jmmv __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
34 1.1 jmmv The NetBSD Foundation, inc. All rights reserved.");
35 1.20 rillig __RCSID("$NetBSD: t_snprintb.c,v 1.20 2024/02/16 19:53:40 rillig Exp $");
36 1.1 jmmv
37 1.9 rillig #include <stdio.h>
38 1.1 jmmv #include <string.h>
39 1.1 jmmv #include <util.h>
40 1.9 rillig #include <vis.h>
41 1.1 jmmv
42 1.1 jmmv #include <atf-c.h>
43 1.1 jmmv
44 1.9 rillig static const char *
45 1.15 rillig vis_arr(const char *arr, size_t arrsize)
46 1.9 rillig {
47 1.10 rillig static char buf[6][1024];
48 1.9 rillig static size_t i;
49 1.9 rillig
50 1.10 rillig i = (i + 1) % (sizeof(buf) / sizeof(buf[0]));
51 1.15 rillig int rv = strnvisx(buf[i], sizeof(buf[i]), arr, arrsize,
52 1.10 rillig VIS_WHITE | VIS_OCTAL);
53 1.15 rillig ATF_REQUIRE_MSG(rv >= 0, "strnvisx failed for size %zu", arrsize);
54 1.9 rillig return buf[i];
55 1.9 rillig }
56 1.9 rillig
57 1.1 jmmv static void
58 1.15 rillig check_unmodified_loc(const char *file, size_t line,
59 1.15 rillig const char *arr, size_t begin, size_t end)
60 1.15 rillig {
61 1.15 rillig size_t mod_begin = begin, mod_end = end;
62 1.15 rillig while (mod_begin < mod_end && arr[mod_begin] == 'Z')
63 1.15 rillig mod_begin++;
64 1.15 rillig while (mod_begin < mod_end && arr[mod_end - 1] == 'Z')
65 1.15 rillig mod_end--;
66 1.15 rillig ATF_CHECK_MSG(
67 1.15 rillig mod_begin == mod_end,
68 1.15 rillig "failed:\n"
69 1.15 rillig "\ttest case: %s:%zu\n"
70 1.15 rillig "\tout-of-bounds write from %zu to %zu: %s\n",
71 1.15 rillig file, line,
72 1.15 rillig mod_begin, mod_end, vis_arr(arr + mod_begin, mod_end - mod_begin));
73 1.15 rillig }
74 1.15 rillig
75 1.15 rillig static void
76 1.10 rillig h_snprintb_loc(const char *file, size_t line,
77 1.10 rillig size_t bufsize, const char *fmt, size_t fmtlen, uint64_t val,
78 1.10 rillig int exp_rv, const char *res, size_t reslen)
79 1.1 jmmv {
80 1.9 rillig char buf[1024];
81 1.9 rillig
82 1.10 rillig ATF_REQUIRE(bufsize <= sizeof(buf));
83 1.15 rillig ATF_REQUIRE(reslen <= sizeof(buf));
84 1.10 rillig
85 1.10 rillig memset(buf, 'Z', sizeof(buf));
86 1.10 rillig int rv = snprintb(buf, bufsize, fmt, val);
87 1.10 rillig ATF_REQUIRE(rv >= 0);
88 1.10 rillig size_t rlen = rv;
89 1.1 jmmv
90 1.20 rillig if (bufsize == 0 && reslen == 1)
91 1.20 rillig reslen = 0;
92 1.9 rillig ATF_CHECK_MSG(
93 1.20 rillig rv == exp_rv
94 1.20 rillig && memcmp(buf, res, reslen) == 0
95 1.10 rillig && buf[rlen < bufsize ? rlen : bufsize - 1] == '\0',
96 1.9 rillig "failed:\n"
97 1.9 rillig "\ttest case: %s:%zu\n"
98 1.9 rillig "\tformat: %s\n"
99 1.9 rillig "\tvalue: %#jx\n"
100 1.10 rillig "\twant: %d bytes %s\n"
101 1.10 rillig "\thave: %d bytes %s\n",
102 1.9 rillig file, line,
103 1.11 rillig vis_arr(fmt, fmtlen),
104 1.11 rillig (uintmax_t)val,
105 1.10 rillig exp_rv, vis_arr(res, reslen),
106 1.10 rillig rv, vis_arr(buf, reslen));
107 1.16 rillig check_unmodified_loc(file, line, buf, reslen, sizeof(buf));
108 1.1 jmmv }
109 1.1 jmmv
110 1.10 rillig #define h_snprintb_len(bufsize, fmt, val, exp_rv, res) \
111 1.10 rillig h_snprintb_loc(__FILE__, __LINE__, \
112 1.10 rillig bufsize, fmt, sizeof(fmt) - 1, val, \
113 1.16 rillig exp_rv, res, sizeof(res))
114 1.9 rillig #define h_snprintb(fmt, val, res) \
115 1.10 rillig h_snprintb_len(1024, fmt, val, sizeof(res) - 1, res)
116 1.10 rillig
117 1.10 rillig static void
118 1.10 rillig h_snprintb_error_loc(const char *file, size_t line,
119 1.10 rillig const char *fmt, size_t fmtlen)
120 1.10 rillig {
121 1.10 rillig char buf[1024];
122 1.10 rillig
123 1.10 rillig memset(buf, 'Z', sizeof(buf));
124 1.10 rillig int rv = snprintb(buf, sizeof(buf), fmt, 0);
125 1.10 rillig size_t buflen = rv;
126 1.10 rillig
127 1.10 rillig ATF_REQUIRE(rv >= -1);
128 1.10 rillig ATF_CHECK_MSG(rv == -1,
129 1.10 rillig "expected error but got success:\n"
130 1.10 rillig "\ttest case: %s:%zu\n"
131 1.10 rillig "\tformat: %s\n"
132 1.10 rillig "\tresult: %zu bytes %s\n",
133 1.10 rillig file, line,
134 1.10 rillig vis_arr(fmt, fmtlen),
135 1.10 rillig buflen, vis_arr(buf, buflen));
136 1.10 rillig }
137 1.10 rillig
138 1.10 rillig #define h_snprintb_error(fmt) \
139 1.10 rillig h_snprintb_error_loc(__FILE__, __LINE__, fmt, sizeof(fmt) - 1)
140 1.9 rillig
141 1.1 jmmv ATF_TC(snprintb);
142 1.1 jmmv ATF_TC_HEAD(snprintb, tc)
143 1.1 jmmv {
144 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks snprintb(3)");
145 1.1 jmmv }
146 1.1 jmmv ATF_TC_BODY(snprintb, tc)
147 1.1 jmmv {
148 1.10 rillig
149 1.10 rillig // old-style format, octal
150 1.9 rillig h_snprintb(
151 1.9 rillig "\010"
152 1.9 rillig "\002BITTWO"
153 1.9 rillig "\001BITONE",
154 1.9 rillig 3,
155 1.9 rillig "03<BITTWO,BITONE>");
156 1.9 rillig
157 1.10 rillig // old-style format, decimal
158 1.9 rillig h_snprintb(
159 1.10 rillig "\012"
160 1.10 rillig "\0011"
161 1.10 rillig "\0119"
162 1.10 rillig "\02117"
163 1.10 rillig "\04032",
164 1.10 rillig 0xffffffff,
165 1.10 rillig "4294967295<1,9,17,32>");
166 1.10 rillig
167 1.10 rillig // old-style format, hexadecimal, from msb downto lsb
168 1.10 rillig h_snprintb(
169 1.10 rillig "\020"
170 1.10 rillig "\04032"
171 1.10 rillig "\03024"
172 1.10 rillig "\02016"
173 1.10 rillig "\0108"
174 1.10 rillig "\0077"
175 1.10 rillig "\0066"
176 1.10 rillig "\0055"
177 1.10 rillig "\0044"
178 1.10 rillig "\0033"
179 1.10 rillig "\0022"
180 1.10 rillig "\0011"
181 1.10 rillig // The old-style format supports only 32 bits, interpreting the
182 1.10 rillig // \041 as part of the text belonging to bit 1.
183 1.10 rillig "\04133",
184 1.12 rillig 0x0000ffff00ff0f35,
185 1.10 rillig "0xffff00ff0f35<24,6,5,3,1!33>");
186 1.10 rillig
187 1.10 rillig // old-style format, hexadecimal, from lsb to msb
188 1.10 rillig h_snprintb(
189 1.10 rillig "\020"
190 1.10 rillig "\0011"
191 1.10 rillig "\0022"
192 1.10 rillig "\0033"
193 1.10 rillig "\0044"
194 1.10 rillig "\0055"
195 1.10 rillig "\0066"
196 1.10 rillig "\0077"
197 1.10 rillig "\0108"
198 1.10 rillig "\02016"
199 1.10 rillig "\03024"
200 1.10 rillig "\04032"
201 1.10 rillig // The old-style format supports only 32 bits, interpreting the
202 1.10 rillig // \041 as part of the text belonging to bit 32.
203 1.10 rillig "\04133",
204 1.12 rillig 0xffff0000ff00f0ca,
205 1.10 rillig "0xffff0000ff00f0ca<2,4,7,8,16,32!33>");
206 1.10 rillig
207 1.10 rillig // The bits can be listed in arbitrary order, there can also be
208 1.10 rillig // duplicates. A bit's description can be empty, resulting in several
209 1.10 rillig // commas in a row.
210 1.10 rillig h_snprintb(
211 1.10 rillig "\020"
212 1.10 rillig "\001lsb"
213 1.10 rillig "\040msb"
214 1.10 rillig "\011"
215 1.10 rillig "\012"
216 1.10 rillig "\002above-lsb"
217 1.10 rillig "\037below-msb"
218 1.10 rillig "\001lsb-again"
219 1.10 rillig "\040msb-again",
220 1.10 rillig 0xc0000303,
221 1.10 rillig "0xc0000303<lsb,msb,,,above-lsb,below-msb,lsb-again,msb-again>");
222 1.10 rillig
223 1.10 rillig #if 0
224 1.10 rillig // If the first bit number is 33 or more, snprintb invokes undefined
225 1.10 rillig // behavior due to an out-of-bounds bit shift, though undetected by
226 1.10 rillig // -ftrapv. Later bit numbers are properly checked.
227 1.10 rillig h_snprintb(
228 1.10 rillig "\020"
229 1.10 rillig "\177undefined_behavior"
230 1.10 rillig "\001lsb",
231 1.12 rillig 0xffffffffffffffff,
232 1.10 rillig "0xffffffffffffffff<?>");
233 1.10 rillig #endif
234 1.10 rillig
235 1.10 rillig // old-style format, invalid number base 0
236 1.10 rillig h_snprintb_error(
237 1.10 rillig "");
238 1.10 rillig
239 1.10 rillig // old-style format, invalid number base 2
240 1.10 rillig h_snprintb_error(
241 1.10 rillig "\002");
242 1.10 rillig
243 1.10 rillig // old-style format, invalid number base 255 or -1
244 1.10 rillig h_snprintb_error(
245 1.10 rillig "\377");
246 1.10 rillig
247 1.20 rillig // old-style format, small buffers
248 1.10 rillig h_snprintb_len(
249 1.10 rillig 0, "\020", 0,
250 1.16 rillig 1, "");
251 1.10 rillig h_snprintb_len(
252 1.10 rillig 1, "\020", 0,
253 1.16 rillig 1, "");
254 1.10 rillig h_snprintb_len(
255 1.10 rillig 2, "\020", 0,
256 1.16 rillig 1, "0");
257 1.10 rillig h_snprintb_len(
258 1.10 rillig 3, "\020", 0,
259 1.16 rillig 1, "0");
260 1.10 rillig h_snprintb_len(
261 1.10 rillig 3, "\020", 7,
262 1.16 rillig 3, "0x");
263 1.10 rillig h_snprintb_len(
264 1.10 rillig 4, "\020", 7,
265 1.16 rillig 3, "0x7");
266 1.10 rillig h_snprintb_len(
267 1.10 rillig 7, "\020\001lsb", 7,
268 1.16 rillig 8, "0x7<ls");
269 1.10 rillig h_snprintb_len(
270 1.10 rillig 8, "\020\001lsb", 7,
271 1.16 rillig 8, "0x7<lsb");
272 1.10 rillig h_snprintb_len(
273 1.10 rillig 9, "\020\001lsb", 7,
274 1.16 rillig 8, "0x7<lsb>");
275 1.10 rillig h_snprintb_len(
276 1.10 rillig 9, "\020\001one\002two", 7,
277 1.16 rillig 12, "0x7<one,");
278 1.10 rillig h_snprintb_len(
279 1.10 rillig 10, "\020\001one\002two", 7,
280 1.16 rillig 12, "0x7<one,t");
281 1.10 rillig h_snprintb_len(
282 1.10 rillig 12, "\020\001one\002two", 7,
283 1.16 rillig 12, "0x7<one,two");
284 1.10 rillig h_snprintb_len(
285 1.10 rillig 13, "\020\001one\002two", 7,
286 1.16 rillig 12, "0x7<one,two>");
287 1.10 rillig
288 1.10 rillig // new-style format, single bits, octal
289 1.10 rillig h_snprintb(
290 1.10 rillig "\177\010"
291 1.10 rillig "b\000bit0\0"
292 1.10 rillig "b\037bit31\0"
293 1.10 rillig "b\040bit32\0"
294 1.10 rillig "b\077bit63\0",
295 1.12 rillig 0xf000000ff000000f,
296 1.10 rillig "01700000000776000000017<bit0,bit31,bit32,bit63>");
297 1.10 rillig
298 1.10 rillig // new-style format, single bits, decimal
299 1.10 rillig h_snprintb(
300 1.10 rillig "\177\012"
301 1.10 rillig "b\000bit0\0"
302 1.10 rillig "b\037bit31\0"
303 1.10 rillig "b\040bit32\0"
304 1.10 rillig "b\077bit63\0",
305 1.12 rillig 0xf000000ff000000f,
306 1.10 rillig "17293822637553745935<bit0,bit31,bit32,bit63>");
307 1.9 rillig
308 1.10 rillig // new-style format, single bits, hexadecimal
309 1.10 rillig h_snprintb(
310 1.10 rillig "\177\020"
311 1.10 rillig "b\000bit0\0"
312 1.10 rillig "b\037bit31\0"
313 1.10 rillig "b\040bit32\0"
314 1.10 rillig "b\077bit63\0",
315 1.12 rillig 0xf000000ff000000f,
316 1.10 rillig "0xf000000ff000000f<bit0,bit31,bit32,bit63>");
317 1.10 rillig
318 1.10 rillig // new-style format, invalid number base 2
319 1.10 rillig h_snprintb_error(
320 1.10 rillig "\177\002");
321 1.10 rillig
322 1.10 rillig // new-style format, invalid number base 255 or -1
323 1.10 rillig h_snprintb_error(
324 1.10 rillig "\177\377");
325 1.10 rillig
326 1.10 rillig // new-style format, single bits, edge cases
327 1.10 rillig //
328 1.10 rillig // The bits can be listed in arbitrary order, there can also be
329 1.10 rillig // duplicates. A bit's description can be empty, resulting in several
330 1.10 rillig // commas in a row.
331 1.9 rillig h_snprintb(
332 1.9 rillig "\177\020"
333 1.10 rillig "b\01lsb\0"
334 1.10 rillig "b\02\0"
335 1.10 rillig "b\03\0"
336 1.9 rillig "b\05NOTBOOT\0"
337 1.9 rillig "b\06FPP\0"
338 1.9 rillig "b\13SDVMA\0"
339 1.9 rillig "b\15VIDEO\0"
340 1.9 rillig "b\20LORES\0"
341 1.9 rillig "b\21FPA\0"
342 1.9 rillig "b\22DIAG\0"
343 1.9 rillig "b\16CACHE\0"
344 1.9 rillig "b\17IOCACHE\0"
345 1.9 rillig "b\22LOOPBACK\0"
346 1.9 rillig "b\04DBGCACHE\0",
347 1.10 rillig 0xe86f,
348 1.10 rillig "0xe86f<lsb,,,NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
349 1.10 rillig
350 1.10 rillig // new-style format, octal, named bit-field
351 1.10 rillig h_snprintb(
352 1.10 rillig "\177\010"
353 1.10 rillig "f\010\004Field\0"
354 1.10 rillig "=\001one\0"
355 1.10 rillig "=\002two\0",
356 1.10 rillig 0x100,
357 1.10 rillig "0400<Field=01=one>");
358 1.10 rillig
359 1.10 rillig // new-style format, decimal, named bit-field
360 1.10 rillig h_snprintb(
361 1.10 rillig "\177\012"
362 1.10 rillig "f\010\004Field\0"
363 1.10 rillig "=\1one\0"
364 1.10 rillig "=\2two\0",
365 1.10 rillig 0x100,
366 1.10 rillig "256<Field=1=one>");
367 1.10 rillig
368 1.10 rillig // new-style format, hexadecimal, named bit-field
369 1.10 rillig h_snprintb(
370 1.10 rillig "\177\020"
371 1.10 rillig "f\010\004Field\0"
372 1.10 rillig "=\1one\0"
373 1.10 rillig "=\2two\0",
374 1.10 rillig 0x100,
375 1.10 rillig "0x100<Field=0x1=one>");
376 1.10 rillig
377 1.10 rillig // new-style format, octal, unnamed bit-field
378 1.10 rillig h_snprintb(
379 1.10 rillig "\177\010"
380 1.10 rillig "F\010\004Field\0"
381 1.10 rillig ":\001one\0"
382 1.10 rillig ":\002two\0",
383 1.10 rillig 0x100,
384 1.10 rillig "0400<one>");
385 1.10 rillig
386 1.10 rillig // new-style format, decimal, unnamed bit-field
387 1.10 rillig h_snprintb(
388 1.10 rillig "\177\012"
389 1.10 rillig "F\010\004Field\0"
390 1.10 rillig ":\1one\0"
391 1.10 rillig ":\2two\0",
392 1.10 rillig 0x100,
393 1.10 rillig "256<one>");
394 1.9 rillig
395 1.10 rillig // new-style format, hexadecimal, unnamed bit-field
396 1.9 rillig h_snprintb(
397 1.10 rillig "\177\020"
398 1.10 rillig "F\010\004Field\0"
399 1.10 rillig ":\1one\0"
400 1.10 rillig ":\2two\0",
401 1.10 rillig 0x100,
402 1.10 rillig "0x100<one>");
403 1.10 rillig
404 1.10 rillig // new-style format, hexadecimal, named bit-field, edge cases
405 1.10 rillig //
406 1.10 rillig // Field values can be listed in arbitrary order, there can also be
407 1.10 rillig // duplicates. A field value's description can be empty, resulting in
408 1.10 rillig // several '=' in a row. The ':' directive can emulate the '='
409 1.10 rillig // directive, but not vice versa.
410 1.10 rillig h_snprintb(
411 1.10 rillig "\177\20"
412 1.10 rillig "f\0\4Field\0"
413 1.10 rillig "=\1one\0"
414 1.10 rillig "=\1one-again\0"
415 1.10 rillig "=\1\0"
416 1.10 rillig "=\1\0"
417 1.10 rillig ":\1double\0"
418 1.10 rillig ":\1-colon\0"
419 1.10 rillig ":\1=equal\0"
420 1.9 rillig "=\2TWO\0",
421 1.9 rillig 1,
422 1.10 rillig "0x1<Field=0x1=one=one-again==double-colon=equal>");
423 1.10 rillig
424 1.10 rillig // new-style format, hexadecimal, unnamed bit-field, edge cases
425 1.10 rillig //
426 1.10 rillig // Combining the 'F' and '=' directives generates output that doesn't
427 1.10 rillig // look well-formed.
428 1.10 rillig h_snprintb(
429 1.10 rillig "\177\20"
430 1.10 rillig "=\0all-zero\0"
431 1.10 rillig "=\1all-one\0"
432 1.10 rillig ":\1-continued\0"
433 1.10 rillig "F\0\4Field\0"
434 1.10 rillig "=\1one\0"
435 1.10 rillig "=\1one-again\0"
436 1.10 rillig "=\1\0"
437 1.10 rillig "=\1\0"
438 1.10 rillig ":\1double\0"
439 1.10 rillig ":\1-colon\0"
440 1.10 rillig ":\1=equal\0"
441 1.9 rillig "=\2TWO\0",
442 1.9 rillig 1,
443 1.10 rillig "0x1=all-one-continued<=one=one-again==double-colon=equal>");
444 1.10 rillig
445 1.10 rillig // new-style format, bit-fields with fixed fallback value
446 1.10 rillig //
447 1.10 rillig // Only the first fallback value is used, all others are ignored.
448 1.9 rillig h_snprintb(
449 1.10 rillig "\177\020"
450 1.10 rillig "f\0\4Field\0"
451 1.10 rillig "=\1one\0"
452 1.10 rillig "=\2two\0"
453 1.10 rillig "*=other\0"
454 1.10 rillig "*=yet-another\0"
455 1.10 rillig "b\1separator\0"
456 1.10 rillig "F\0\4Field\0"
457 1.10 rillig ":\1one\0"
458 1.10 rillig ":\2two\0"
459 1.10 rillig "*other\0"
460 1.10 rillig "*yet-another\0",
461 1.10 rillig 3,
462 1.10 rillig "0x3<Field=0x3=other,separator,other>");
463 1.5 ryo
464 1.10 rillig // new-style format, bit-fields with numeric fallback value
465 1.9 rillig h_snprintb(
466 1.10 rillig "\177\020"
467 1.10 rillig "f\010\004Field\0"
468 1.10 rillig "*=other(%04ju)\0"
469 1.10 rillig "b\000separator\0"
470 1.10 rillig "F\010\004Field\0"
471 1.10 rillig "*other(%04ju)\0",
472 1.10 rillig 0x301,
473 1.10 rillig "0x301<Field=0x3=other(0003),separator,other(0003)>");
474 1.10 rillig
475 1.10 rillig // new-style format, bit-field with more than 8 bits
476 1.10 rillig //
477 1.10 rillig // The '=' and ':' directives can only match values from 0 to 255, so
478 1.10 rillig // the fallback value always steps in. The complete value of the
479 1.10 rillig // bit-field appears in the output, though.
480 1.9 rillig h_snprintb(
481 1.9 rillig "\177\020"
482 1.10 rillig "f\010\020Field\0"
483 1.10 rillig "=\377ones\0"
484 1.10 rillig "*=other(%jx)\0"
485 1.10 rillig "F\010\020\0"
486 1.10 rillig ":\377ones\0"
487 1.10 rillig "*other(%jx)\0",
488 1.10 rillig 0x77ff55,
489 1.10 rillig "0x77ff55<Field=0x77ff=other(77ff),other(77ff)>");
490 1.6 kre
491 1.17 rillig // new-style format, bit-field with 8 bits
492 1.17 rillig h_snprintb(
493 1.17 rillig "\177\020"
494 1.17 rillig "F\010\010\0"
495 1.17 rillig ":\377all\0"
496 1.17 rillig "*other\0",
497 1.17 rillig 0xff00,
498 1.18 rillig "0xff00<all>");
499 1.17 rillig
500 1.10 rillig // new-style format, bit-fields with no match
501 1.9 rillig h_snprintb(
502 1.10 rillig "\177\020"
503 1.10 rillig "f\010\004Field\0"
504 1.10 rillig "=\1one\0"
505 1.10 rillig "=\2two\0",
506 1.10 rillig 0x301,
507 1.10 rillig "0x301<Field=0x3>");
508 1.9 rillig h_snprintb(
509 1.10 rillig "\177\020"
510 1.10 rillig "F\010\004\0"
511 1.10 rillig ":\1one\0"
512 1.10 rillig ":\2two\0",
513 1.10 rillig 0x301,
514 1.10 rillig "0x301<>");
515 1.9 rillig h_snprintb(
516 1.9 rillig "\177\020"
517 1.10 rillig "f\010\004Field\0"
518 1.10 rillig "=\1one\0"
519 1.10 rillig "=\2two\0"
520 1.10 rillig "b\000separator\0"
521 1.10 rillig "F\010\004\0"
522 1.10 rillig ":\1one\0"
523 1.10 rillig ":\2two\0",
524 1.10 rillig 0x301,
525 1.10 rillig "0x301<Field=0x3,separator,>");
526 1.6 kre
527 1.10 rillig // new-style format, two separate bit-fields
528 1.9 rillig h_snprintb(
529 1.9 rillig "\177\20"
530 1.9 rillig "f\0\4Field_1\0"
531 1.9 rillig "=\1ONE\0"
532 1.9 rillig "=\2TWO\0"
533 1.9 rillig "f\4\4Field_2\0"
534 1.9 rillig "=\1ONE\0"
535 1.9 rillig "=\2TWO\0",
536 1.9 rillig 0x12,
537 1.6 kre "0x12<Field_1=0x2=TWO,Field_2=0x1=ONE>");
538 1.6 kre
539 1.10 rillig // new-style format, mixed named and unnamed bit-fields
540 1.9 rillig h_snprintb(
541 1.9 rillig "\177\20"
542 1.9 rillig "f\0\4Field_1\0"
543 1.9 rillig "=\1ONE\0"
544 1.9 rillig "=\2TWO\0"
545 1.9 rillig "F\x8\4\0"
546 1.9 rillig "*Field_3=%jd\0"
547 1.9 rillig "f\4\4Field_2\0"
548 1.9 rillig ":\1:ONE\0"
549 1.9 rillig ":\2:TWO\0",
550 1.9 rillig 0xD12,
551 1.6 kre "0xd12<Field_1=0x2=TWO,Field_3=13,Field_2=0x1:ONE>");
552 1.9 rillig
553 1.10 rillig // new-style format, descriptions with spaces
554 1.10 rillig h_snprintb(
555 1.10 rillig "\177\020"
556 1.10 rillig "b\000has std options\0"
557 1.10 rillig "f\010\004std options\0"
558 1.10 rillig "=\000no options\0"
559 1.10 rillig "=\017all options\0"
560 1.10 rillig "F\020\004ext options\0"
561 1.10 rillig ":\000no ext options\0"
562 1.10 rillig ":\017all ext options\0",
563 1.10 rillig 0x000001,
564 1.10 rillig "0x1<has std options,std options=0=no options,no ext options>");
565 1.10 rillig h_snprintb(
566 1.10 rillig "\177\020"
567 1.10 rillig "f\010\004std options\0"
568 1.10 rillig "*=other std options\0"
569 1.10 rillig "F\020\004ext\toptions\0"
570 1.10 rillig "*other\text\toptions\0",
571 1.10 rillig 0x000001,
572 1.10 rillig "0x1<std options=0=other std options,other\text\toptions>");
573 1.10 rillig
574 1.9 rillig // It is possible but cumbersome to implement a reduced variant of
575 1.9 rillig // rot13 using snprintb, shown here for lowercase letters only.
576 1.9 rillig for (char ch = 'A'; ch <= '~'; ch++) {
577 1.9 rillig char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
578 1.9 rillig : ch >= 'n' && ch <= 'z' ? ch - 13
579 1.9 rillig : '?';
580 1.9 rillig char expected[8];
581 1.9 rillig ATF_REQUIRE_EQ(7,
582 1.9 rillig snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
583 1.9 rillig h_snprintb(
584 1.9 rillig "\177\020"
585 1.9 rillig "F\000\010\0"
586 1.9 rillig ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
587 1.9 rillig ":iv\0:jw\0:kx\0:ly\0:mz\0"
588 1.9 rillig ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
589 1.9 rillig ":vi\0:wj\0:xk\0:yl\0:zm\0"
590 1.9 rillig // If snprintf accepted "%jc", it would be possible to
591 1.9 rillig // echo the non-alphabetic characters instead of a
592 1.9 rillig // catchall question mark.
593 1.9 rillig "*?\0",
594 1.9 rillig ch,
595 1.9 rillig expected);
596 1.9 rillig }
597 1.15 rillig
598 1.20 rillig // new-style format, small buffers
599 1.15 rillig h_snprintb_len(
600 1.15 rillig 0, "\177\020", 0,
601 1.16 rillig 1, "");
602 1.15 rillig h_snprintb_len(
603 1.15 rillig 1, "\177\020", 0,
604 1.16 rillig 1, "");
605 1.15 rillig h_snprintb_len(
606 1.15 rillig 2, "\177\020", 0,
607 1.16 rillig 1, "0");
608 1.15 rillig h_snprintb_len(
609 1.15 rillig 3, "\177\020", 0,
610 1.16 rillig 1, "0");
611 1.15 rillig h_snprintb_len(
612 1.15 rillig 3, "\177\020", 7,
613 1.16 rillig 3, "0x");
614 1.15 rillig h_snprintb_len(
615 1.15 rillig 4, "\177\020", 7,
616 1.16 rillig 3, "0x7");
617 1.15 rillig h_snprintb_len(
618 1.15 rillig 7, "\177\020b\000lsb\0", 7,
619 1.16 rillig 8, "0x7<ls");
620 1.15 rillig h_snprintb_len(
621 1.15 rillig 8, "\177\020b\000lsb\0", 7,
622 1.16 rillig 8, "0x7<lsb");
623 1.15 rillig h_snprintb_len(
624 1.15 rillig 9, "\177\020b\000lsb\0", 7,
625 1.16 rillig 8, "0x7<lsb>");
626 1.15 rillig h_snprintb_len(
627 1.15 rillig 9, "\177\020b\000one\0b\001two\0", 7,
628 1.16 rillig 12, "0x7<one,");
629 1.15 rillig h_snprintb_len(
630 1.15 rillig 10, "\177\020b\000one\0b\001two\0", 7,
631 1.16 rillig 12, "0x7<one,t");
632 1.15 rillig h_snprintb_len(
633 1.15 rillig 12, "\177\020b\000one\0b\001two\0", 7,
634 1.16 rillig 12, "0x7<one,two");
635 1.15 rillig h_snprintb_len(
636 1.15 rillig 13, "\177\020b\000one\0b\001two\0", 7,
637 1.16 rillig 12, "0x7<one,two>");
638 1.15 rillig
639 1.1 jmmv }
640 1.1 jmmv
641 1.2 pgoyette static void
642 1.10 rillig h_snprintb_m_loc(const char *file, size_t line,
643 1.13 rillig size_t bufsize, const char *fmt, size_t fmtlen, uint64_t val, size_t max,
644 1.13 rillig size_t exp_rv, const char *res, size_t reslen)
645 1.2 pgoyette {
646 1.2 pgoyette char buf[1024];
647 1.2 pgoyette
648 1.20 rillig ATF_REQUIRE(bufsize > 0);
649 1.13 rillig ATF_REQUIRE(bufsize <= sizeof(buf));
650 1.15 rillig ATF_REQUIRE(reslen <= sizeof(buf));
651 1.2 pgoyette
652 1.13 rillig memset(buf, 'Z', sizeof(buf));
653 1.13 rillig int rv = snprintb_m(buf, bufsize, fmt, val, max);
654 1.13 rillig ATF_REQUIRE_MSG(rv >= 0,
655 1.13 rillig "formatting %jx with '%s' returns error %d",
656 1.10 rillig (uintmax_t)val, vis_arr(fmt, fmtlen), rv);
657 1.9 rillig
658 1.13 rillig size_t total = rv;
659 1.9 rillig ATF_CHECK_MSG(
660 1.13 rillig total == exp_rv && memcmp(buf, res, reslen) == 0,
661 1.9 rillig "failed:\n"
662 1.9 rillig "\ttest case: %s:%zu\n"
663 1.9 rillig "\tformat: %s\n"
664 1.9 rillig "\tvalue: %#jx\n"
665 1.13 rillig "\tmax: %zu\n"
666 1.9 rillig "\twant: %zu bytes %s\n"
667 1.9 rillig "\thave: %zu bytes %s\n",
668 1.9 rillig file, line,
669 1.11 rillig vis_arr(fmt, fmtlen),
670 1.11 rillig (uintmax_t)val,
671 1.13 rillig max,
672 1.13 rillig exp_rv, vis_arr(res, reslen),
673 1.13 rillig total, vis_arr(buf, reslen));
674 1.16 rillig check_unmodified_loc(file, line, buf, reslen, sizeof(buf));
675 1.2 pgoyette }
676 1.2 pgoyette
677 1.13 rillig #define h_snprintb_m_len(bufsize, fmt, val, line_max, exp_rv, res) \
678 1.10 rillig h_snprintb_m_loc(__FILE__, __LINE__, \
679 1.13 rillig bufsize, fmt, sizeof(fmt) - 1, val, line_max, \
680 1.16 rillig exp_rv, res, sizeof(res))
681 1.13 rillig #define h_snprintb_m(fmt, val, max, res) \
682 1.13 rillig h_snprintb_m_len(1024, fmt, val, max, sizeof(res) - 1, res)
683 1.9 rillig
684 1.2 pgoyette ATF_TC(snprintb_m);
685 1.2 pgoyette ATF_TC_HEAD(snprintb_m, tc)
686 1.2 pgoyette {
687 1.2 pgoyette atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
688 1.2 pgoyette }
689 1.2 pgoyette ATF_TC_BODY(snprintb_m, tc)
690 1.2 pgoyette {
691 1.13 rillig // old-style format, small maximum line length
692 1.13 rillig h_snprintb_m_len(
693 1.13 rillig 68,
694 1.13 rillig "\020"
695 1.13 rillig "\001bit1"
696 1.13 rillig "\002bit2"
697 1.13 rillig "\003bit3",
698 1.13 rillig 0xffff,
699 1.13 rillig 6,
700 1.13 rillig 143,
701 1.16 rillig "0xffff>\0"
702 1.16 rillig "0xffff<>\0"
703 1.16 rillig "0xffffb>\0"
704 1.16 rillig "0xffffi>\0"
705 1.16 rillig "0xfffft>\0"
706 1.16 rillig "0xffff1>\0"
707 1.16 rillig "0xffff<>\0"
708 1.16 rillig "0xff\0"
709 1.13 rillig );
710 1.13 rillig
711 1.13 rillig // new-style format, small maximum line length
712 1.13 rillig h_snprintb_m_len(
713 1.13 rillig 68,
714 1.13 rillig "\177\020"
715 1.13 rillig "b\000bit1\0"
716 1.13 rillig "b\001bit2\0"
717 1.13 rillig "b\002bit3\0",
718 1.13 rillig 0xffff,
719 1.13 rillig 6,
720 1.13 rillig 143,
721 1.16 rillig "0xffff>\0"
722 1.16 rillig "0xffff<>\0"
723 1.16 rillig "0xffffb>\0"
724 1.16 rillig "0xffffi>\0"
725 1.16 rillig "0xfffft>\0"
726 1.16 rillig "0xffff1>\0"
727 1.16 rillig "0xffff<>\0"
728 1.16 rillig "0xff\0"
729 1.16 rillig );
730 1.16 rillig
731 1.16 rillig // new-style format, buffer too small for number
732 1.16 rillig h_snprintb_m_len(
733 1.16 rillig 2,
734 1.16 rillig "\177\020",
735 1.16 rillig 0,
736 1.16 rillig 64,
737 1.16 rillig 2,
738 1.16 rillig "\0"
739 1.16 rillig );
740 1.16 rillig
741 1.16 rillig // new-style format, buffer too small for '<'
742 1.16 rillig h_snprintb_m_len(
743 1.16 rillig 6,
744 1.16 rillig "\177\020"
745 1.16 rillig "b\000lsb\0",
746 1.16 rillig 0xff,
747 1.16 rillig 64,
748 1.16 rillig 10,
749 1.16 rillig "0xff\0"
750 1.13 rillig );
751 1.13 rillig
752 1.15 rillig // new-style format, buffer too small for description
753 1.15 rillig h_snprintb_m_len(
754 1.16 rillig 7,
755 1.15 rillig "\177\020"
756 1.16 rillig "b\000lsb\0",
757 1.16 rillig 0xff,
758 1.15 rillig 64,
759 1.15 rillig 10,
760 1.16 rillig "0xff<\0"
761 1.16 rillig );
762 1.16 rillig
763 1.16 rillig // new-style format, buffer too small for complete description
764 1.16 rillig h_snprintb_m_len(
765 1.16 rillig 9,
766 1.16 rillig "\177\020"
767 1.16 rillig "b\000lsb\0",
768 1.16 rillig 0xff,
769 1.16 rillig 64,
770 1.16 rillig 10,
771 1.16 rillig "0xff<ls\0"
772 1.16 rillig );
773 1.16 rillig
774 1.16 rillig // new-style format, buffer too small for '>'
775 1.16 rillig h_snprintb_m_len(
776 1.16 rillig 10,
777 1.16 rillig "\177\020"
778 1.16 rillig "b\000lsb\0",
779 1.16 rillig 0xff,
780 1.16 rillig 64,
781 1.16 rillig 10,
782 1.16 rillig "0xff<lsb\0"
783 1.16 rillig );
784 1.16 rillig
785 1.16 rillig // new-style format, buffer too small for second line
786 1.16 rillig h_snprintb_m_len(
787 1.16 rillig 11,
788 1.16 rillig "\177\020"
789 1.16 rillig "b\000lsb\0"
790 1.16 rillig "b\001two\0",
791 1.16 rillig 0xff,
792 1.16 rillig 11,
793 1.16 rillig 20,
794 1.16 rillig "0xff<lsb>\0"
795 1.16 rillig );
796 1.16 rillig
797 1.16 rillig // new-style format, buffer too small for number in line 2
798 1.16 rillig h_snprintb_m_len(
799 1.16 rillig 12,
800 1.16 rillig "\177\020"
801 1.16 rillig "b\000lsb\0"
802 1.16 rillig "b\001two\0",
803 1.16 rillig 0xff,
804 1.16 rillig 11,
805 1.16 rillig 20,
806 1.16 rillig "0xff<lsb>\0"
807 1.16 rillig "\0"
808 1.16 rillig );
809 1.16 rillig
810 1.16 rillig // new-style format, buffer too small for complete number in line 2
811 1.16 rillig h_snprintb_m_len(
812 1.16 rillig 15,
813 1.16 rillig "\177\020"
814 1.16 rillig "b\000lsb\0"
815 1.16 rillig "b\001two\0",
816 1.16 rillig 0xff,
817 1.16 rillig 11,
818 1.16 rillig 20,
819 1.16 rillig "0xff<lsb>\0"
820 1.16 rillig "0xf\0" // XXX: incomplete number may be misleading
821 1.16 rillig );
822 1.16 rillig
823 1.16 rillig // new-style format, buffer too small for '<' in line 2
824 1.16 rillig h_snprintb_m_len(
825 1.16 rillig 16,
826 1.16 rillig "\177\020"
827 1.16 rillig "b\000lsb\0"
828 1.16 rillig "b\001two\0",
829 1.16 rillig 0xff,
830 1.16 rillig 11,
831 1.16 rillig 20,
832 1.16 rillig "0xff<lsb>\0"
833 1.16 rillig "0xff\0"
834 1.16 rillig );
835 1.16 rillig
836 1.16 rillig // new-style format, buffer too small for description in line 2
837 1.16 rillig h_snprintb_m_len(
838 1.16 rillig 17,
839 1.16 rillig "\177\020"
840 1.16 rillig "b\000lsb\0"
841 1.16 rillig "b\001two\0",
842 1.16 rillig 0xff,
843 1.16 rillig 11,
844 1.16 rillig 20,
845 1.16 rillig "0xff<lsb>\0"
846 1.16 rillig "0xff<\0"
847 1.16 rillig );
848 1.16 rillig
849 1.16 rillig // new-style format, line too small for unmatched field value
850 1.16 rillig h_snprintb_m_len(
851 1.16 rillig 30,
852 1.16 rillig "\177\020"
853 1.16 rillig "f\000\004bits\0"
854 1.16 rillig ":\000other\0",
855 1.16 rillig 0xff,
856 1.16 rillig 11,
857 1.16 rillig 22,
858 1.16 rillig "0xff<bits=0xf>\0" // XXX: line too long (14 > 11)
859 1.16 rillig "0xff#>\0" // XXX: why '#'? unbalanced '<>'
860 1.16 rillig );
861 1.16 rillig
862 1.16 rillig // new-style format, line too small for field value
863 1.16 rillig h_snprintb_m_len(
864 1.16 rillig 30,
865 1.16 rillig "\177\020"
866 1.16 rillig "f\000\004bits\0"
867 1.16 rillig ":\017other\0",
868 1.16 rillig 0xff,
869 1.16 rillig 11,
870 1.16 rillig 27,
871 1.16 rillig "0xff<bits=0xf>\0" // XXX: line too long (14 > 11)
872 1.16 rillig "0xff#other>\0" // XXX: unbalanced '<>'
873 1.16 rillig );
874 1.16 rillig
875 1.16 rillig // new-style format, buffer too small for fallback
876 1.16 rillig h_snprintb_m_len(
877 1.16 rillig 20,
878 1.16 rillig "\177\020"
879 1.16 rillig "f\000\004bits\0"
880 1.16 rillig "*=fallback\0"
881 1.16 rillig "b\0024\0",
882 1.16 rillig 0xff,
883 1.16 rillig 64,
884 1.16 rillig 26,
885 1.16 rillig "0xff<bits=0xf=fall\0"
886 1.15 rillig );
887 1.15 rillig
888 1.19 rillig // new-style format, buffer too small for numeric fallback
889 1.19 rillig h_snprintb_m_len(
890 1.19 rillig 20,
891 1.19 rillig "\177\020"
892 1.19 rillig "F\000\004\0"
893 1.19 rillig "*fallback(%040jd)\0",
894 1.19 rillig 0xff,
895 1.19 rillig 64,
896 1.19 rillig 57,
897 1.19 rillig "0xff<fallback(0000\0"
898 1.19 rillig );
899 1.19 rillig
900 1.19 rillig // new-style format, buffer too small for numeric fallback past buffer
901 1.19 rillig h_snprintb_m_len(
902 1.19 rillig 15,
903 1.19 rillig "\177\020"
904 1.19 rillig "F\000\004\0"
905 1.19 rillig "*fallback(%010jd)\0"
906 1.19 rillig "F\004\004\0"
907 1.19 rillig "*fallback(%010jd)\0",
908 1.19 rillig 0xff,
909 1.19 rillig 64,
910 1.19 rillig 48,
911 1.19 rillig "0xff<fallback\0"
912 1.19 rillig );
913 1.19 rillig
914 1.9 rillig h_snprintb_m(
915 1.9 rillig "\177\020"
916 1.9 rillig "b\0LSB\0"
917 1.9 rillig "b\1_BITONE\0"
918 1.9 rillig "f\4\4NIBBLE2\0"
919 1.9 rillig "f\x10\4BURST\0"
920 1.9 rillig "=\04FOUR\0"
921 1.9 rillig "=\17FIFTEEN\0"
922 1.9 rillig "b\x1fMSB\0",
923 1.9 rillig 0x800f0701,
924 1.9 rillig 33,
925 1.9 rillig "0x800f0701<LSB,NIBBLE2=0>\0"
926 1.16 rillig "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0"
927 1.16 rillig );
928 1.9 rillig
929 1.9 rillig h_snprintb_m(
930 1.9 rillig "\177\020"
931 1.9 rillig "b\0LSB\0"
932 1.9 rillig "b\1_BITONE\0"
933 1.9 rillig "f\4\4NIBBLE2\0"
934 1.9 rillig "f\x10\4BURST\0"
935 1.9 rillig "=\04FOUR\0"
936 1.9 rillig "=\17FIFTEEN\0"
937 1.9 rillig "b\x1fMSB\0",
938 1.9 rillig 0x800f0701,
939 1.9 rillig 32,
940 1.9 rillig "0x800f0701<LSB,NIBBLE2=0>\0"
941 1.9 rillig "0x800f0701<BURST=0xf=FIFTEEN>\0"
942 1.9 rillig "0x800f0701<MSB>\0");
943 1.2 pgoyette }
944 1.2 pgoyette
945 1.1 jmmv ATF_TP_ADD_TCS(tp)
946 1.1 jmmv {
947 1.1 jmmv
948 1.1 jmmv ATF_TP_ADD_TC(tp, snprintb);
949 1.2 pgoyette ATF_TP_ADD_TC(tp, snprintb_m);
950 1.1 jmmv
951 1.1 jmmv return atf_no_error();
952 1.1 jmmv }
953