t_snprintb.c revision 1.19 1 1.19 rillig /* $NetBSD: t_snprintb.c,v 1.19 2024/02/16 19:20:38 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.19 rillig __RCSID("$NetBSD: t_snprintb.c,v 1.19 2024/02/16 19:20:38 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 // Calling snprintb with bufsize == 0 invokes undefined
83 1.10 rillig // behavior due to out-of-range 'bp'.
84 1.10 rillig ATF_REQUIRE(bufsize > 0);
85 1.10 rillig ATF_REQUIRE(bufsize <= sizeof(buf));
86 1.15 rillig ATF_REQUIRE(reslen <= sizeof(buf));
87 1.10 rillig
88 1.10 rillig memset(buf, 'Z', sizeof(buf));
89 1.10 rillig int rv = snprintb(buf, bufsize, fmt, val);
90 1.10 rillig ATF_REQUIRE(rv >= 0);
91 1.10 rillig size_t rlen = rv;
92 1.1 jmmv
93 1.9 rillig ATF_CHECK_MSG(
94 1.10 rillig rv == exp_rv && 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.10 rillig // old-style format, small buffer
248 1.10 rillig #if 0
249 1.10 rillig // FIXME: Calling snprintb with buffer size 0 invokes undefined
250 1.10 rillig // behavior due to out-of-bounds 'bp' pointer.
251 1.10 rillig h_snprintb_len(
252 1.10 rillig 0, "\020", 0,
253 1.16 rillig 1, "");
254 1.10 rillig #endif
255 1.10 rillig h_snprintb_len(
256 1.10 rillig 1, "\020", 0,
257 1.16 rillig 1, "");
258 1.10 rillig h_snprintb_len(
259 1.10 rillig 2, "\020", 0,
260 1.16 rillig 1, "0");
261 1.10 rillig h_snprintb_len(
262 1.10 rillig 3, "\020", 0,
263 1.16 rillig 1, "0");
264 1.10 rillig h_snprintb_len(
265 1.10 rillig 3, "\020", 7,
266 1.16 rillig 3, "0x");
267 1.10 rillig h_snprintb_len(
268 1.10 rillig 4, "\020", 7,
269 1.16 rillig 3, "0x7");
270 1.10 rillig h_snprintb_len(
271 1.10 rillig 7, "\020\001lsb", 7,
272 1.16 rillig 8, "0x7<ls");
273 1.10 rillig h_snprintb_len(
274 1.10 rillig 8, "\020\001lsb", 7,
275 1.16 rillig 8, "0x7<lsb");
276 1.10 rillig h_snprintb_len(
277 1.10 rillig 9, "\020\001lsb", 7,
278 1.16 rillig 8, "0x7<lsb>");
279 1.10 rillig h_snprintb_len(
280 1.10 rillig 9, "\020\001one\002two", 7,
281 1.16 rillig 12, "0x7<one,");
282 1.10 rillig h_snprintb_len(
283 1.10 rillig 10, "\020\001one\002two", 7,
284 1.16 rillig 12, "0x7<one,t");
285 1.10 rillig h_snprintb_len(
286 1.10 rillig 12, "\020\001one\002two", 7,
287 1.16 rillig 12, "0x7<one,two");
288 1.10 rillig h_snprintb_len(
289 1.10 rillig 13, "\020\001one\002two", 7,
290 1.16 rillig 12, "0x7<one,two>");
291 1.10 rillig
292 1.10 rillig // new-style format, single bits, octal
293 1.10 rillig h_snprintb(
294 1.10 rillig "\177\010"
295 1.10 rillig "b\000bit0\0"
296 1.10 rillig "b\037bit31\0"
297 1.10 rillig "b\040bit32\0"
298 1.10 rillig "b\077bit63\0",
299 1.12 rillig 0xf000000ff000000f,
300 1.10 rillig "01700000000776000000017<bit0,bit31,bit32,bit63>");
301 1.10 rillig
302 1.10 rillig // new-style format, single bits, decimal
303 1.10 rillig h_snprintb(
304 1.10 rillig "\177\012"
305 1.10 rillig "b\000bit0\0"
306 1.10 rillig "b\037bit31\0"
307 1.10 rillig "b\040bit32\0"
308 1.10 rillig "b\077bit63\0",
309 1.12 rillig 0xf000000ff000000f,
310 1.10 rillig "17293822637553745935<bit0,bit31,bit32,bit63>");
311 1.9 rillig
312 1.10 rillig // new-style format, single bits, hexadecimal
313 1.10 rillig h_snprintb(
314 1.10 rillig "\177\020"
315 1.10 rillig "b\000bit0\0"
316 1.10 rillig "b\037bit31\0"
317 1.10 rillig "b\040bit32\0"
318 1.10 rillig "b\077bit63\0",
319 1.12 rillig 0xf000000ff000000f,
320 1.10 rillig "0xf000000ff000000f<bit0,bit31,bit32,bit63>");
321 1.10 rillig
322 1.10 rillig // new-style format, invalid number base 2
323 1.10 rillig h_snprintb_error(
324 1.10 rillig "\177\002");
325 1.10 rillig
326 1.10 rillig // new-style format, invalid number base 255 or -1
327 1.10 rillig h_snprintb_error(
328 1.10 rillig "\177\377");
329 1.10 rillig
330 1.10 rillig // new-style format, single bits, edge cases
331 1.10 rillig //
332 1.10 rillig // The bits can be listed in arbitrary order, there can also be
333 1.10 rillig // duplicates. A bit's description can be empty, resulting in several
334 1.10 rillig // commas in a row.
335 1.9 rillig h_snprintb(
336 1.9 rillig "\177\020"
337 1.10 rillig "b\01lsb\0"
338 1.10 rillig "b\02\0"
339 1.10 rillig "b\03\0"
340 1.9 rillig "b\05NOTBOOT\0"
341 1.9 rillig "b\06FPP\0"
342 1.9 rillig "b\13SDVMA\0"
343 1.9 rillig "b\15VIDEO\0"
344 1.9 rillig "b\20LORES\0"
345 1.9 rillig "b\21FPA\0"
346 1.9 rillig "b\22DIAG\0"
347 1.9 rillig "b\16CACHE\0"
348 1.9 rillig "b\17IOCACHE\0"
349 1.9 rillig "b\22LOOPBACK\0"
350 1.9 rillig "b\04DBGCACHE\0",
351 1.10 rillig 0xe86f,
352 1.10 rillig "0xe86f<lsb,,,NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
353 1.10 rillig
354 1.10 rillig // new-style format, octal, named bit-field
355 1.10 rillig h_snprintb(
356 1.10 rillig "\177\010"
357 1.10 rillig "f\010\004Field\0"
358 1.10 rillig "=\001one\0"
359 1.10 rillig "=\002two\0",
360 1.10 rillig 0x100,
361 1.10 rillig "0400<Field=01=one>");
362 1.10 rillig
363 1.10 rillig // new-style format, decimal, named bit-field
364 1.10 rillig h_snprintb(
365 1.10 rillig "\177\012"
366 1.10 rillig "f\010\004Field\0"
367 1.10 rillig "=\1one\0"
368 1.10 rillig "=\2two\0",
369 1.10 rillig 0x100,
370 1.10 rillig "256<Field=1=one>");
371 1.10 rillig
372 1.10 rillig // new-style format, hexadecimal, named bit-field
373 1.10 rillig h_snprintb(
374 1.10 rillig "\177\020"
375 1.10 rillig "f\010\004Field\0"
376 1.10 rillig "=\1one\0"
377 1.10 rillig "=\2two\0",
378 1.10 rillig 0x100,
379 1.10 rillig "0x100<Field=0x1=one>");
380 1.10 rillig
381 1.10 rillig // new-style format, octal, unnamed bit-field
382 1.10 rillig h_snprintb(
383 1.10 rillig "\177\010"
384 1.10 rillig "F\010\004Field\0"
385 1.10 rillig ":\001one\0"
386 1.10 rillig ":\002two\0",
387 1.10 rillig 0x100,
388 1.10 rillig "0400<one>");
389 1.10 rillig
390 1.10 rillig // new-style format, decimal, unnamed bit-field
391 1.10 rillig h_snprintb(
392 1.10 rillig "\177\012"
393 1.10 rillig "F\010\004Field\0"
394 1.10 rillig ":\1one\0"
395 1.10 rillig ":\2two\0",
396 1.10 rillig 0x100,
397 1.10 rillig "256<one>");
398 1.9 rillig
399 1.10 rillig // new-style format, hexadecimal, unnamed bit-field
400 1.9 rillig h_snprintb(
401 1.10 rillig "\177\020"
402 1.10 rillig "F\010\004Field\0"
403 1.10 rillig ":\1one\0"
404 1.10 rillig ":\2two\0",
405 1.10 rillig 0x100,
406 1.10 rillig "0x100<one>");
407 1.10 rillig
408 1.10 rillig // new-style format, hexadecimal, named bit-field, edge cases
409 1.10 rillig //
410 1.10 rillig // Field values can be listed in arbitrary order, there can also be
411 1.10 rillig // duplicates. A field value's description can be empty, resulting in
412 1.10 rillig // several '=' in a row. The ':' directive can emulate the '='
413 1.10 rillig // directive, but not vice versa.
414 1.10 rillig h_snprintb(
415 1.10 rillig "\177\20"
416 1.10 rillig "f\0\4Field\0"
417 1.10 rillig "=\1one\0"
418 1.10 rillig "=\1one-again\0"
419 1.10 rillig "=\1\0"
420 1.10 rillig "=\1\0"
421 1.10 rillig ":\1double\0"
422 1.10 rillig ":\1-colon\0"
423 1.10 rillig ":\1=equal\0"
424 1.9 rillig "=\2TWO\0",
425 1.9 rillig 1,
426 1.10 rillig "0x1<Field=0x1=one=one-again==double-colon=equal>");
427 1.10 rillig
428 1.10 rillig // new-style format, hexadecimal, unnamed bit-field, edge cases
429 1.10 rillig //
430 1.10 rillig // Combining the 'F' and '=' directives generates output that doesn't
431 1.10 rillig // look well-formed.
432 1.10 rillig h_snprintb(
433 1.10 rillig "\177\20"
434 1.10 rillig "=\0all-zero\0"
435 1.10 rillig "=\1all-one\0"
436 1.10 rillig ":\1-continued\0"
437 1.10 rillig "F\0\4Field\0"
438 1.10 rillig "=\1one\0"
439 1.10 rillig "=\1one-again\0"
440 1.10 rillig "=\1\0"
441 1.10 rillig "=\1\0"
442 1.10 rillig ":\1double\0"
443 1.10 rillig ":\1-colon\0"
444 1.10 rillig ":\1=equal\0"
445 1.9 rillig "=\2TWO\0",
446 1.9 rillig 1,
447 1.10 rillig "0x1=all-one-continued<=one=one-again==double-colon=equal>");
448 1.10 rillig
449 1.10 rillig // new-style format, bit-fields with fixed fallback value
450 1.10 rillig //
451 1.10 rillig // Only the first fallback value is used, all others are ignored.
452 1.9 rillig h_snprintb(
453 1.10 rillig "\177\020"
454 1.10 rillig "f\0\4Field\0"
455 1.10 rillig "=\1one\0"
456 1.10 rillig "=\2two\0"
457 1.10 rillig "*=other\0"
458 1.10 rillig "*=yet-another\0"
459 1.10 rillig "b\1separator\0"
460 1.10 rillig "F\0\4Field\0"
461 1.10 rillig ":\1one\0"
462 1.10 rillig ":\2two\0"
463 1.10 rillig "*other\0"
464 1.10 rillig "*yet-another\0",
465 1.10 rillig 3,
466 1.10 rillig "0x3<Field=0x3=other,separator,other>");
467 1.5 ryo
468 1.10 rillig // new-style format, bit-fields with numeric fallback value
469 1.9 rillig h_snprintb(
470 1.10 rillig "\177\020"
471 1.10 rillig "f\010\004Field\0"
472 1.10 rillig "*=other(%04ju)\0"
473 1.10 rillig "b\000separator\0"
474 1.10 rillig "F\010\004Field\0"
475 1.10 rillig "*other(%04ju)\0",
476 1.10 rillig 0x301,
477 1.10 rillig "0x301<Field=0x3=other(0003),separator,other(0003)>");
478 1.10 rillig
479 1.10 rillig // new-style format, bit-field with more than 8 bits
480 1.10 rillig //
481 1.10 rillig // The '=' and ':' directives can only match values from 0 to 255, so
482 1.10 rillig // the fallback value always steps in. The complete value of the
483 1.10 rillig // bit-field appears in the output, though.
484 1.9 rillig h_snprintb(
485 1.9 rillig "\177\020"
486 1.10 rillig "f\010\020Field\0"
487 1.10 rillig "=\377ones\0"
488 1.10 rillig "*=other(%jx)\0"
489 1.10 rillig "F\010\020\0"
490 1.10 rillig ":\377ones\0"
491 1.10 rillig "*other(%jx)\0",
492 1.10 rillig 0x77ff55,
493 1.10 rillig "0x77ff55<Field=0x77ff=other(77ff),other(77ff)>");
494 1.6 kre
495 1.17 rillig // new-style format, bit-field with 8 bits
496 1.17 rillig h_snprintb(
497 1.17 rillig "\177\020"
498 1.17 rillig "F\010\010\0"
499 1.17 rillig ":\377all\0"
500 1.17 rillig "*other\0",
501 1.17 rillig 0xff00,
502 1.18 rillig "0xff00<all>");
503 1.17 rillig
504 1.10 rillig // new-style format, bit-fields with no match
505 1.9 rillig h_snprintb(
506 1.10 rillig "\177\020"
507 1.10 rillig "f\010\004Field\0"
508 1.10 rillig "=\1one\0"
509 1.10 rillig "=\2two\0",
510 1.10 rillig 0x301,
511 1.10 rillig "0x301<Field=0x3>");
512 1.9 rillig h_snprintb(
513 1.10 rillig "\177\020"
514 1.10 rillig "F\010\004\0"
515 1.10 rillig ":\1one\0"
516 1.10 rillig ":\2two\0",
517 1.10 rillig 0x301,
518 1.10 rillig "0x301<>");
519 1.9 rillig h_snprintb(
520 1.9 rillig "\177\020"
521 1.10 rillig "f\010\004Field\0"
522 1.10 rillig "=\1one\0"
523 1.10 rillig "=\2two\0"
524 1.10 rillig "b\000separator\0"
525 1.10 rillig "F\010\004\0"
526 1.10 rillig ":\1one\0"
527 1.10 rillig ":\2two\0",
528 1.10 rillig 0x301,
529 1.10 rillig "0x301<Field=0x3,separator,>");
530 1.6 kre
531 1.10 rillig // new-style format, two separate bit-fields
532 1.9 rillig h_snprintb(
533 1.9 rillig "\177\20"
534 1.9 rillig "f\0\4Field_1\0"
535 1.9 rillig "=\1ONE\0"
536 1.9 rillig "=\2TWO\0"
537 1.9 rillig "f\4\4Field_2\0"
538 1.9 rillig "=\1ONE\0"
539 1.9 rillig "=\2TWO\0",
540 1.9 rillig 0x12,
541 1.6 kre "0x12<Field_1=0x2=TWO,Field_2=0x1=ONE>");
542 1.6 kre
543 1.10 rillig // new-style format, mixed named and unnamed bit-fields
544 1.9 rillig h_snprintb(
545 1.9 rillig "\177\20"
546 1.9 rillig "f\0\4Field_1\0"
547 1.9 rillig "=\1ONE\0"
548 1.9 rillig "=\2TWO\0"
549 1.9 rillig "F\x8\4\0"
550 1.9 rillig "*Field_3=%jd\0"
551 1.9 rillig "f\4\4Field_2\0"
552 1.9 rillig ":\1:ONE\0"
553 1.9 rillig ":\2:TWO\0",
554 1.9 rillig 0xD12,
555 1.6 kre "0xd12<Field_1=0x2=TWO,Field_3=13,Field_2=0x1:ONE>");
556 1.9 rillig
557 1.10 rillig // new-style format, descriptions with spaces
558 1.10 rillig h_snprintb(
559 1.10 rillig "\177\020"
560 1.10 rillig "b\000has std options\0"
561 1.10 rillig "f\010\004std options\0"
562 1.10 rillig "=\000no options\0"
563 1.10 rillig "=\017all options\0"
564 1.10 rillig "F\020\004ext options\0"
565 1.10 rillig ":\000no ext options\0"
566 1.10 rillig ":\017all ext options\0",
567 1.10 rillig 0x000001,
568 1.10 rillig "0x1<has std options,std options=0=no options,no ext options>");
569 1.10 rillig h_snprintb(
570 1.10 rillig "\177\020"
571 1.10 rillig "f\010\004std options\0"
572 1.10 rillig "*=other std options\0"
573 1.10 rillig "F\020\004ext\toptions\0"
574 1.10 rillig "*other\text\toptions\0",
575 1.10 rillig 0x000001,
576 1.10 rillig "0x1<std options=0=other std options,other\text\toptions>");
577 1.10 rillig
578 1.9 rillig // It is possible but cumbersome to implement a reduced variant of
579 1.9 rillig // rot13 using snprintb, shown here for lowercase letters only.
580 1.9 rillig for (char ch = 'A'; ch <= '~'; ch++) {
581 1.9 rillig char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
582 1.9 rillig : ch >= 'n' && ch <= 'z' ? ch - 13
583 1.9 rillig : '?';
584 1.9 rillig char expected[8];
585 1.9 rillig ATF_REQUIRE_EQ(7,
586 1.9 rillig snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
587 1.9 rillig h_snprintb(
588 1.9 rillig "\177\020"
589 1.9 rillig "F\000\010\0"
590 1.9 rillig ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
591 1.9 rillig ":iv\0:jw\0:kx\0:ly\0:mz\0"
592 1.9 rillig ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
593 1.9 rillig ":vi\0:wj\0:xk\0:yl\0:zm\0"
594 1.9 rillig // If snprintf accepted "%jc", it would be possible to
595 1.9 rillig // echo the non-alphabetic characters instead of a
596 1.9 rillig // catchall question mark.
597 1.9 rillig "*?\0",
598 1.9 rillig ch,
599 1.9 rillig expected);
600 1.9 rillig }
601 1.15 rillig
602 1.15 rillig // new-style format, small buffer
603 1.15 rillig #if 0
604 1.15 rillig // FIXME: Calling snprintb with buffer size 0 invokes undefined
605 1.15 rillig // behavior due to out-of-bounds 'bp' pointer.
606 1.15 rillig h_snprintb_len(
607 1.15 rillig 0, "\177\020", 0,
608 1.16 rillig 1, "");
609 1.15 rillig #endif
610 1.15 rillig h_snprintb_len(
611 1.15 rillig 1, "\177\020", 0,
612 1.16 rillig 1, "");
613 1.15 rillig h_snprintb_len(
614 1.15 rillig 2, "\177\020", 0,
615 1.16 rillig 1, "0");
616 1.15 rillig h_snprintb_len(
617 1.15 rillig 3, "\177\020", 0,
618 1.16 rillig 1, "0");
619 1.15 rillig h_snprintb_len(
620 1.15 rillig 3, "\177\020", 7,
621 1.16 rillig 3, "0x");
622 1.15 rillig h_snprintb_len(
623 1.15 rillig 4, "\177\020", 7,
624 1.16 rillig 3, "0x7");
625 1.15 rillig h_snprintb_len(
626 1.15 rillig 7, "\177\020b\000lsb\0", 7,
627 1.16 rillig 8, "0x7<ls");
628 1.15 rillig h_snprintb_len(
629 1.15 rillig 8, "\177\020b\000lsb\0", 7,
630 1.16 rillig 8, "0x7<lsb");
631 1.15 rillig h_snprintb_len(
632 1.15 rillig 9, "\177\020b\000lsb\0", 7,
633 1.16 rillig 8, "0x7<lsb>");
634 1.15 rillig h_snprintb_len(
635 1.15 rillig 9, "\177\020b\000one\0b\001two\0", 7,
636 1.16 rillig 12, "0x7<one,");
637 1.15 rillig h_snprintb_len(
638 1.15 rillig 10, "\177\020b\000one\0b\001two\0", 7,
639 1.16 rillig 12, "0x7<one,t");
640 1.15 rillig h_snprintb_len(
641 1.15 rillig 12, "\177\020b\000one\0b\001two\0", 7,
642 1.16 rillig 12, "0x7<one,two");
643 1.15 rillig h_snprintb_len(
644 1.15 rillig 13, "\177\020b\000one\0b\001two\0", 7,
645 1.16 rillig 12, "0x7<one,two>");
646 1.15 rillig
647 1.1 jmmv }
648 1.1 jmmv
649 1.2 pgoyette static void
650 1.10 rillig h_snprintb_m_loc(const char *file, size_t line,
651 1.13 rillig size_t bufsize, const char *fmt, size_t fmtlen, uint64_t val, size_t max,
652 1.13 rillig size_t exp_rv, const char *res, size_t reslen)
653 1.2 pgoyette {
654 1.2 pgoyette char buf[1024];
655 1.2 pgoyette
656 1.13 rillig ATF_REQUIRE(bufsize > 1);
657 1.13 rillig ATF_REQUIRE(bufsize <= sizeof(buf));
658 1.15 rillig ATF_REQUIRE(reslen <= sizeof(buf));
659 1.2 pgoyette
660 1.13 rillig memset(buf, 'Z', sizeof(buf));
661 1.13 rillig int rv = snprintb_m(buf, bufsize, fmt, val, max);
662 1.13 rillig ATF_REQUIRE_MSG(rv >= 0,
663 1.13 rillig "formatting %jx with '%s' returns error %d",
664 1.10 rillig (uintmax_t)val, vis_arr(fmt, fmtlen), rv);
665 1.9 rillig
666 1.13 rillig size_t total = rv;
667 1.9 rillig ATF_CHECK_MSG(
668 1.13 rillig total == exp_rv && memcmp(buf, res, reslen) == 0,
669 1.9 rillig "failed:\n"
670 1.9 rillig "\ttest case: %s:%zu\n"
671 1.9 rillig "\tformat: %s\n"
672 1.9 rillig "\tvalue: %#jx\n"
673 1.13 rillig "\tmax: %zu\n"
674 1.9 rillig "\twant: %zu bytes %s\n"
675 1.9 rillig "\thave: %zu bytes %s\n",
676 1.9 rillig file, line,
677 1.11 rillig vis_arr(fmt, fmtlen),
678 1.11 rillig (uintmax_t)val,
679 1.13 rillig max,
680 1.13 rillig exp_rv, vis_arr(res, reslen),
681 1.13 rillig total, vis_arr(buf, reslen));
682 1.16 rillig check_unmodified_loc(file, line, buf, reslen, sizeof(buf));
683 1.2 pgoyette }
684 1.2 pgoyette
685 1.13 rillig #define h_snprintb_m_len(bufsize, fmt, val, line_max, exp_rv, res) \
686 1.10 rillig h_snprintb_m_loc(__FILE__, __LINE__, \
687 1.13 rillig bufsize, fmt, sizeof(fmt) - 1, val, line_max, \
688 1.16 rillig exp_rv, res, sizeof(res))
689 1.13 rillig #define h_snprintb_m(fmt, val, max, res) \
690 1.13 rillig h_snprintb_m_len(1024, fmt, val, max, sizeof(res) - 1, res)
691 1.9 rillig
692 1.2 pgoyette ATF_TC(snprintb_m);
693 1.2 pgoyette ATF_TC_HEAD(snprintb_m, tc)
694 1.2 pgoyette {
695 1.2 pgoyette atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
696 1.2 pgoyette }
697 1.2 pgoyette ATF_TC_BODY(snprintb_m, tc)
698 1.2 pgoyette {
699 1.13 rillig // old-style format, small maximum line length
700 1.13 rillig h_snprintb_m_len(
701 1.13 rillig 68,
702 1.13 rillig "\020"
703 1.13 rillig "\001bit1"
704 1.13 rillig "\002bit2"
705 1.13 rillig "\003bit3",
706 1.13 rillig 0xffff,
707 1.13 rillig 6,
708 1.13 rillig 143,
709 1.16 rillig "0xffff>\0"
710 1.16 rillig "0xffff<>\0"
711 1.16 rillig "0xffffb>\0"
712 1.16 rillig "0xffffi>\0"
713 1.16 rillig "0xfffft>\0"
714 1.16 rillig "0xffff1>\0"
715 1.16 rillig "0xffff<>\0"
716 1.16 rillig "0xff\0"
717 1.13 rillig );
718 1.13 rillig
719 1.13 rillig // new-style format, small maximum line length
720 1.13 rillig h_snprintb_m_len(
721 1.13 rillig 68,
722 1.13 rillig "\177\020"
723 1.13 rillig "b\000bit1\0"
724 1.13 rillig "b\001bit2\0"
725 1.13 rillig "b\002bit3\0",
726 1.13 rillig 0xffff,
727 1.13 rillig 6,
728 1.13 rillig 143,
729 1.16 rillig "0xffff>\0"
730 1.16 rillig "0xffff<>\0"
731 1.16 rillig "0xffffb>\0"
732 1.16 rillig "0xffffi>\0"
733 1.16 rillig "0xfffft>\0"
734 1.16 rillig "0xffff1>\0"
735 1.16 rillig "0xffff<>\0"
736 1.16 rillig "0xff\0"
737 1.16 rillig );
738 1.16 rillig
739 1.16 rillig // new-style format, buffer too small for number
740 1.16 rillig h_snprintb_m_len(
741 1.16 rillig 2,
742 1.16 rillig "\177\020",
743 1.16 rillig 0,
744 1.16 rillig 64,
745 1.16 rillig 2,
746 1.16 rillig "\0"
747 1.16 rillig );
748 1.16 rillig
749 1.16 rillig // new-style format, buffer too small for '<'
750 1.16 rillig h_snprintb_m_len(
751 1.16 rillig 6,
752 1.16 rillig "\177\020"
753 1.16 rillig "b\000lsb\0",
754 1.16 rillig 0xff,
755 1.16 rillig 64,
756 1.16 rillig 10,
757 1.16 rillig "0xff\0"
758 1.13 rillig );
759 1.13 rillig
760 1.15 rillig // new-style format, buffer too small for description
761 1.15 rillig h_snprintb_m_len(
762 1.16 rillig 7,
763 1.15 rillig "\177\020"
764 1.16 rillig "b\000lsb\0",
765 1.16 rillig 0xff,
766 1.15 rillig 64,
767 1.15 rillig 10,
768 1.16 rillig "0xff<\0"
769 1.16 rillig );
770 1.16 rillig
771 1.16 rillig // new-style format, buffer too small for complete description
772 1.16 rillig h_snprintb_m_len(
773 1.16 rillig 9,
774 1.16 rillig "\177\020"
775 1.16 rillig "b\000lsb\0",
776 1.16 rillig 0xff,
777 1.16 rillig 64,
778 1.16 rillig 10,
779 1.16 rillig "0xff<ls\0"
780 1.16 rillig );
781 1.16 rillig
782 1.16 rillig // new-style format, buffer too small for '>'
783 1.16 rillig h_snprintb_m_len(
784 1.16 rillig 10,
785 1.16 rillig "\177\020"
786 1.16 rillig "b\000lsb\0",
787 1.16 rillig 0xff,
788 1.16 rillig 64,
789 1.16 rillig 10,
790 1.16 rillig "0xff<lsb\0"
791 1.16 rillig );
792 1.16 rillig
793 1.16 rillig // new-style format, buffer too small for second line
794 1.16 rillig h_snprintb_m_len(
795 1.16 rillig 11,
796 1.16 rillig "\177\020"
797 1.16 rillig "b\000lsb\0"
798 1.16 rillig "b\001two\0",
799 1.16 rillig 0xff,
800 1.16 rillig 11,
801 1.16 rillig 20,
802 1.16 rillig "0xff<lsb>\0"
803 1.16 rillig );
804 1.16 rillig
805 1.16 rillig // new-style format, buffer too small for number in line 2
806 1.16 rillig h_snprintb_m_len(
807 1.16 rillig 12,
808 1.16 rillig "\177\020"
809 1.16 rillig "b\000lsb\0"
810 1.16 rillig "b\001two\0",
811 1.16 rillig 0xff,
812 1.16 rillig 11,
813 1.16 rillig 20,
814 1.16 rillig "0xff<lsb>\0"
815 1.16 rillig "\0"
816 1.16 rillig );
817 1.16 rillig
818 1.16 rillig // new-style format, buffer too small for complete number in line 2
819 1.16 rillig h_snprintb_m_len(
820 1.16 rillig 15,
821 1.16 rillig "\177\020"
822 1.16 rillig "b\000lsb\0"
823 1.16 rillig "b\001two\0",
824 1.16 rillig 0xff,
825 1.16 rillig 11,
826 1.16 rillig 20,
827 1.16 rillig "0xff<lsb>\0"
828 1.16 rillig "0xf\0" // XXX: incomplete number may be misleading
829 1.16 rillig );
830 1.16 rillig
831 1.16 rillig // new-style format, buffer too small for '<' in line 2
832 1.16 rillig h_snprintb_m_len(
833 1.16 rillig 16,
834 1.16 rillig "\177\020"
835 1.16 rillig "b\000lsb\0"
836 1.16 rillig "b\001two\0",
837 1.16 rillig 0xff,
838 1.16 rillig 11,
839 1.16 rillig 20,
840 1.16 rillig "0xff<lsb>\0"
841 1.16 rillig "0xff\0"
842 1.16 rillig );
843 1.16 rillig
844 1.16 rillig // new-style format, buffer too small for description in line 2
845 1.16 rillig h_snprintb_m_len(
846 1.16 rillig 17,
847 1.16 rillig "\177\020"
848 1.16 rillig "b\000lsb\0"
849 1.16 rillig "b\001two\0",
850 1.16 rillig 0xff,
851 1.16 rillig 11,
852 1.16 rillig 20,
853 1.16 rillig "0xff<lsb>\0"
854 1.16 rillig "0xff<\0"
855 1.16 rillig );
856 1.16 rillig
857 1.16 rillig // new-style format, line too small for unmatched field value
858 1.16 rillig h_snprintb_m_len(
859 1.16 rillig 30,
860 1.16 rillig "\177\020"
861 1.16 rillig "f\000\004bits\0"
862 1.16 rillig ":\000other\0",
863 1.16 rillig 0xff,
864 1.16 rillig 11,
865 1.16 rillig 22,
866 1.16 rillig "0xff<bits=0xf>\0" // XXX: line too long (14 > 11)
867 1.16 rillig "0xff#>\0" // XXX: why '#'? unbalanced '<>'
868 1.16 rillig );
869 1.16 rillig
870 1.16 rillig // new-style format, line too small for field value
871 1.16 rillig h_snprintb_m_len(
872 1.16 rillig 30,
873 1.16 rillig "\177\020"
874 1.16 rillig "f\000\004bits\0"
875 1.16 rillig ":\017other\0",
876 1.16 rillig 0xff,
877 1.16 rillig 11,
878 1.16 rillig 27,
879 1.16 rillig "0xff<bits=0xf>\0" // XXX: line too long (14 > 11)
880 1.16 rillig "0xff#other>\0" // XXX: unbalanced '<>'
881 1.16 rillig );
882 1.16 rillig
883 1.16 rillig // new-style format, buffer too small for fallback
884 1.16 rillig h_snprintb_m_len(
885 1.16 rillig 20,
886 1.16 rillig "\177\020"
887 1.16 rillig "f\000\004bits\0"
888 1.16 rillig "*=fallback\0"
889 1.16 rillig "b\0024\0",
890 1.16 rillig 0xff,
891 1.16 rillig 64,
892 1.16 rillig 26,
893 1.16 rillig "0xff<bits=0xf=fall\0"
894 1.15 rillig );
895 1.15 rillig
896 1.19 rillig // new-style format, buffer too small for numeric fallback
897 1.19 rillig h_snprintb_m_len(
898 1.19 rillig 20,
899 1.19 rillig "\177\020"
900 1.19 rillig "F\000\004\0"
901 1.19 rillig "*fallback(%040jd)\0",
902 1.19 rillig 0xff,
903 1.19 rillig 64,
904 1.19 rillig 57,
905 1.19 rillig "0xff<fallback(0000\0"
906 1.19 rillig );
907 1.19 rillig
908 1.19 rillig // new-style format, buffer too small for numeric fallback past buffer
909 1.19 rillig h_snprintb_m_len(
910 1.19 rillig 15,
911 1.19 rillig "\177\020"
912 1.19 rillig "F\000\004\0"
913 1.19 rillig "*fallback(%010jd)\0"
914 1.19 rillig "F\004\004\0"
915 1.19 rillig "*fallback(%010jd)\0",
916 1.19 rillig 0xff,
917 1.19 rillig 64,
918 1.19 rillig 48,
919 1.19 rillig "0xff<fallback\0"
920 1.19 rillig );
921 1.19 rillig
922 1.9 rillig h_snprintb_m(
923 1.9 rillig "\177\020"
924 1.9 rillig "b\0LSB\0"
925 1.9 rillig "b\1_BITONE\0"
926 1.9 rillig "f\4\4NIBBLE2\0"
927 1.9 rillig "f\x10\4BURST\0"
928 1.9 rillig "=\04FOUR\0"
929 1.9 rillig "=\17FIFTEEN\0"
930 1.9 rillig "b\x1fMSB\0",
931 1.9 rillig 0x800f0701,
932 1.9 rillig 33,
933 1.9 rillig "0x800f0701<LSB,NIBBLE2=0>\0"
934 1.16 rillig "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0"
935 1.16 rillig );
936 1.9 rillig
937 1.9 rillig h_snprintb_m(
938 1.9 rillig "\177\020"
939 1.9 rillig "b\0LSB\0"
940 1.9 rillig "b\1_BITONE\0"
941 1.9 rillig "f\4\4NIBBLE2\0"
942 1.9 rillig "f\x10\4BURST\0"
943 1.9 rillig "=\04FOUR\0"
944 1.9 rillig "=\17FIFTEEN\0"
945 1.9 rillig "b\x1fMSB\0",
946 1.9 rillig 0x800f0701,
947 1.9 rillig 32,
948 1.9 rillig "0x800f0701<LSB,NIBBLE2=0>\0"
949 1.9 rillig "0x800f0701<BURST=0xf=FIFTEEN>\0"
950 1.9 rillig "0x800f0701<MSB>\0");
951 1.2 pgoyette }
952 1.2 pgoyette
953 1.1 jmmv ATF_TP_ADD_TCS(tp)
954 1.1 jmmv {
955 1.1 jmmv
956 1.1 jmmv ATF_TP_ADD_TC(tp, snprintb);
957 1.2 pgoyette ATF_TP_ADD_TC(tp, snprintb_m);
958 1.1 jmmv
959 1.1 jmmv return atf_no_error();
960 1.1 jmmv }
961