xref: /xnu-11215.41.3/bsd/kern/subr_sbuf.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1 /*
2  * Copyright (c) 2020 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 #include <kern/kalloc.h>
29 #include <libkern/libkern.h>
30 #include <os/base.h>
31 #include <os/overflow.h>
32 #include <sys/param.h>
33 #include <sys/sbuf.h>
34 #include <sys/uio.h>
35 
36 #if DEBUG || DEVELOPMENT
37 #include <kern/macro_help.h>
38 #include <sys/errno.h>
39 #include <sys/sysctl.h>
40 #endif /* DEBUG || DEVELOPMENT */
41 
42 #define SBUF_ISSET(s, f)        ((s)->s_flags & (f))
43 #define SBUF_SETFLAG(s, f)      do { (s)->s_flags |= (f); } while (0)
44 #define SBUF_CLEARFLAG(s, f)    do { (s)->s_flags &= ~(f); } while (0)
45 
46 #define SBUF_CANEXTEND(s)       SBUF_ISSET(s, SBUF_AUTOEXTEND)
47 #define SBUF_HASOVERFLOWED(s)   SBUF_ISSET(s, SBUF_OVERFLOWED)
48 #define SBUF_ISDYNAMIC(s)       SBUF_ISSET(s, SBUF_DYNAMIC)
49 #define SBUF_ISDYNSTRUCT(s)     SBUF_ISSET(s, SBUF_DYNSTRUCT)
50 #define SBUF_ISFINISHED(s)      SBUF_ISSET(s, SBUF_FINISHED)
51 
52 #define SBUF_MINEXTENDSIZE      16
53 #define SBUF_MAXEXTENDSIZE      PAGE_SIZE
54 #define SBUF_MAXEXTENDINCR      PAGE_SIZE
55 
56 /*!
57  * @function sbuf_delete
58  *
59  * @brief
60  * Destroys an sbuf.  Frees the underlying buffer if it's allocated on the heap
61  * (indicated by SBUF_ISDYNAMIC) and frees the sbuf if it itself is allocated
62  * on the heap (SBUF_ISDYNSTRUCT).
63  *
64  * @param s
65  * The sbuf to destroy.
66  */
67 void
sbuf_delete(struct sbuf * s)68 sbuf_delete(struct sbuf *s)
69 {
70 	if (SBUF_ISDYNAMIC(s) && s->s_buf) {
71 		kfree_data(s->s_buf, s->s_size);
72 		s->s_buf = NULL;
73 	}
74 
75 	if (SBUF_ISDYNSTRUCT(s)) {
76 		kfree_type(struct sbuf, s);
77 	}
78 }
79 
80 /*!
81  * @function sbuf_extendsize
82  *
83  * @brief
84  * Attempts to extend the size of an sbuf to the value pointed to by size.
85  *
86  * @param size
87  * Points to a size_t containing the desired size for input and receives the
88  * actual new size on success (which will be greater than or equal to the
89  * requested size).
90  *
91  * @returns
92  * 0 on success, -1 on failure.
93  */
94 static int
sbuf_extendsize(size_t * size)95 sbuf_extendsize(size_t *size)
96 {
97 	size_t target_size = *size;
98 	size_t new_size;
99 
100 	if (target_size > INT_MAX) {
101 		return -1;
102 	}
103 
104 	if (target_size < SBUF_MAXEXTENDSIZE) {
105 		new_size = SBUF_MINEXTENDSIZE;
106 		while (new_size < target_size) {
107 			new_size *= 2;
108 		}
109 	} else {
110 		/* round up to nearest page: */
111 		new_size = (target_size + PAGE_SIZE - 1) & ~PAGE_MASK;
112 	}
113 
114 	if (new_size > INT_MAX) {
115 		return -1;
116 	}
117 
118 	*size = new_size;
119 	return 0;
120 }
121 
122 /*!
123  * @function sbuf_new
124  *
125  * @brief
126  * Allocates and/or initializes an sbuf.
127  *
128  * @param s
129  * An optional existing sbuf to initialize.  If NULL, a new one is allocated on
130  * the heap.
131  *
132  * @param buf
133  * An optional existing backing buffer to assign to the sbuf.  If NULL, a new
134  * one is allocated on the heap.
135  *
136  * @param length_
137  * The initial size of the sbuf.  The actual size may be greater than this
138  * value.
139  *
140  * @param flags
141  * The flags to set on the sbuf.  Accepted values are:
142  *
143  *   - SBUF_FIXEDLEN:   Do not allow the backing buffer to dynamically expand
144  *                      to accommodate appended data.
145  *   - SBUF_AUTOEXPAND: Automatically reallocate the backing buffer using the
146  *                      heap if required.
147  *
148  * @returns
149  * The new and/or initialized sbuf on success, or NULL on failure.
150  */
151 struct sbuf *
sbuf_new(struct sbuf * s,char * buf,int length_,int flags)152 sbuf_new(struct sbuf *s, char *buf, int length_, int flags)
153 {
154 	size_t length = (size_t)length_;
155 
156 	if (length > INT_MAX || flags & ~SBUF_USRFLAGMSK) {
157 		return NULL;
158 	}
159 
160 	if (s == NULL) {
161 		s = (struct sbuf *)kalloc_type(struct sbuf, Z_WAITOK | Z_ZERO);
162 		if (NULL == s) {
163 			return NULL;
164 		}
165 
166 		s->s_flags = flags;
167 		SBUF_SETFLAG(s, SBUF_DYNSTRUCT);
168 	} else {
169 		bzero(s, sizeof(*s));
170 		s->s_flags = flags;
171 	}
172 
173 	if (buf) {
174 		s->s_size = (int)length;
175 		s->s_buf = buf;
176 		return s;
177 	}
178 
179 	if (SBUF_CANEXTEND(s) && (-1 == sbuf_extendsize(&length))) {
180 		goto fail;
181 	}
182 
183 	/*
184 	 * we always need at least 1 byte for \0, so s_size of 0 will cause an
185 	 * underflow in sbuf_capacity.
186 	 */
187 	if (length == 0) {
188 		goto fail;
189 	}
190 
191 	s->s_buf = kalloc_data(length, Z_WAITOK | Z_ZERO);
192 	if (NULL == s->s_buf) {
193 		goto fail;
194 	}
195 	s->s_size = (int)length;
196 
197 	SBUF_SETFLAG(s, SBUF_DYNAMIC);
198 	return s;
199 
200 fail:
201 	sbuf_delete(s);
202 	return NULL;
203 }
204 
205 /*!
206  * @function sbuf_setpos
207  *
208  * @brief
209  * Set the current position of the sbuf.
210  *
211  * @param s
212  * The sbuf to modify.
213  *
214  * @param pos
215  * The new position to set.  Must be less than or equal to the current position.
216  *
217  * @returns
218  * 0 on success, -1 on failure.
219  */
220 int
sbuf_setpos(struct sbuf * s,int pos)221 sbuf_setpos(struct sbuf *s, int pos)
222 {
223 	if (pos < 0 || pos > s->s_len) {
224 		return -1;
225 	}
226 
227 	s->s_len = pos;
228 	return 0;
229 }
230 
231 /*!
232  * @function sbuf_clear
233  *
234  * @brief
235  * Resets the position/length of the sbuf data to zero and clears the finished
236  * and overflow flags.
237  *
238  * @param s
239  * The sbuf to clear.
240  */
241 void
sbuf_clear(struct sbuf * s)242 sbuf_clear(struct sbuf *s)
243 {
244 	SBUF_CLEARFLAG(s, SBUF_FINISHED);
245 	SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
246 	sbuf_setpos(s, 0);
247 }
248 
249 /*!
250  * @function sbuf_extend
251  *
252  * @brief
253  * Attempt to extend the size of an sbuf's backing buffer by @a addlen bytes.
254  *
255  * @param s
256  * The sbuf to extend.
257  *
258  * @param addlen
259  * How many bytes to increase the size by.
260  *
261  * @returns
262  * 0 on success, -1 on failure.
263  */
264 static int OS_WARN_RESULT
sbuf_extend(struct sbuf * s,size_t addlen)265 sbuf_extend(struct sbuf *s, size_t addlen)
266 {
267 	char *new_buf;
268 	size_t new_size;
269 
270 	if (addlen == 0) {
271 		return 0;
272 	}
273 
274 	if (!SBUF_CANEXTEND(s)) {
275 		return -1;
276 	}
277 
278 	if (os_add_overflow((size_t)s->s_size, addlen, &new_size)) {
279 		return -1;
280 	}
281 
282 	if (-1 == sbuf_extendsize(&new_size)) {
283 		return -1;
284 	}
285 
286 	new_buf = (char *) kalloc_data(new_size, Z_WAITOK);
287 	if (NULL == new_buf) {
288 		return -1;
289 	}
290 
291 	bcopy(s->s_buf, new_buf, (size_t)s->s_size);
292 	if (SBUF_ISDYNAMIC(s)) {
293 		kfree_data(s->s_buf, (size_t)s->s_size);
294 	} else {
295 		SBUF_SETFLAG(s, SBUF_DYNAMIC);
296 	}
297 
298 	s->s_buf = new_buf;
299 	s->s_size = (int)new_size;
300 	return 0;
301 }
302 
303 /*!
304  * @function sbuf_capacity
305  *
306  * @brief
307  * Get the current capacity of an sbuf: how many more bytes we can append given
308  * the current size and position.
309  *
310  * @param s
311  * The sbuf to get the capacity of.
312  *
313  * @returns
314  * The current sbuf capacity.
315  */
316 static size_t
sbuf_capacity(const struct sbuf * s)317 sbuf_capacity(const struct sbuf *s)
318 {
319 	/* 1 byte reserved for \0: */
320 	return (size_t)(s->s_size - s->s_len - 1);
321 }
322 
323 /*!
324  * @function sbuf_ensure_capacity
325  *
326  * @brief
327  * Ensure that an sbuf can accommodate @a add_len bytes, reallocating the
328  * backing buffer if necessary.
329  *
330  * @param s
331  * The sbuf.
332  *
333  * @param wanted
334  * The minimum capacity to ensure @a s has.
335  *
336  * @returns
337  * 0 if the minimum capacity is met by @a s, or -1 on error.
338  */
339 static int
sbuf_ensure_capacity(struct sbuf * s,size_t wanted)340 sbuf_ensure_capacity(struct sbuf *s, size_t wanted)
341 {
342 	size_t size;
343 
344 	size = sbuf_capacity(s);
345 	if (size >= wanted) {
346 		return 0;
347 	}
348 
349 	return sbuf_extend(s, wanted - size);
350 }
351 
352 /*!
353  * @function sbuf_bcat
354  *
355  * @brief
356  * Append data to an sbuf.
357  *
358  * @param s
359  * The sbuf.
360  *
361  * @param data
362  * The data to append.
363  *
364  * @param len
365  * The length of the data.
366  *
367  * @returns
368  * 0 on success, -1 on failure.  Will always fail if the sbuf is marked as
369  * overflowed.
370  */
371 int
sbuf_bcat(struct sbuf * s,const void * data,size_t len)372 sbuf_bcat(struct sbuf *s, const void *data, size_t len)
373 {
374 	if (SBUF_HASOVERFLOWED(s)) {
375 		return -1;
376 	}
377 
378 	if (-1 == sbuf_ensure_capacity(s, len)) {
379 		SBUF_SETFLAG(s, SBUF_OVERFLOWED);
380 		return -1;
381 	}
382 
383 	bcopy(data, s->s_buf + s->s_len, len);
384 	s->s_len += (int)len; /* safe */
385 
386 	return 0;
387 }
388 
389 /*!
390  * @function sbuf_bcpy
391  *
392  * @brief
393  * Set the entire sbuf data, possibly reallocating the backing buffer to
394  * accommodate.
395  *
396  * @param s
397  * The sbuf.
398  *
399  * @param data
400  * The data to set.
401  *
402  * @param len
403  * The length of the data to set.
404  *
405  * @returns
406  * 0 on success or -1 on failure.  Will clear the finished/overflowed flags.
407  */
408 int
sbuf_bcpy(struct sbuf * s,const void * data,size_t len)409 sbuf_bcpy(struct sbuf *s, const void *data, size_t len)
410 {
411 	sbuf_clear(s);
412 	return sbuf_bcat(s, data, len);
413 }
414 
415 /*!
416  * @function sbuf_cat
417  *
418  * @brief
419  * Append a string to an sbuf, possibly expanding the backing buffer to
420  * accommodate.
421  *
422  * @param s
423  * The sbuf.
424  *
425  * @param str
426  * The string to append.
427  *
428  * @returns
429  * 0 on success, -1 on failure.  Always fails if the sbuf is marked as
430  * overflowed.
431  */
432 int
sbuf_cat(struct sbuf * s,const char * str)433 sbuf_cat(struct sbuf *s, const char *str)
434 {
435 	return sbuf_bcat(s, str, strlen(str));
436 }
437 
438 /*!
439  * @function sbuf_cpy
440  *
441  * @brief
442  * Set the entire sbuf data to the given nul-terminated string, possibly
443  * expanding the backing buffer to accommodate it if necessary.
444  *
445  * @param s
446  * The sbuf.
447  *
448  * @param str
449  * The string to set the sbuf data to.
450  *
451  * @returns
452  * 0 on success, -1 on failure.  Clears and resets the sbuf first.
453  */
454 int
sbuf_cpy(struct sbuf * s,const char * str)455 sbuf_cpy(struct sbuf *s, const char *str)
456 {
457 	sbuf_clear(s);
458 	return sbuf_cat(s, str);
459 }
460 
461 /*!
462  * @function sbuf_vprintf
463  *
464  * @brief
465  * Formatted-print into an sbuf using a va_list.
466  *
467  * @param s
468  * The sbuf.
469  *
470  * @param fmt
471  * The format string.
472  *
473  * @param ap
474  * The format string argument data.
475  *
476  * @returns
477  * 0 on success, -1 on failure.  Always fails if the sbuf is marked as
478  * overflowed.
479  */
480 int
sbuf_vprintf(struct sbuf * s,const char * fmt,va_list ap)481 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
482 {
483 	va_list ap_copy;
484 	int result;
485 	size_t capacity;
486 	size_t len;
487 
488 	if (SBUF_HASOVERFLOWED(s)) {
489 		return -1;
490 	}
491 
492 	do {
493 		capacity = sbuf_capacity(s);
494 
495 		va_copy(ap_copy, ap);
496 		/* +1 for \0.  safe because we already accommodate this. */
497 		result = vsnprintf(&s->s_buf[s->s_len], capacity + 1, fmt, ap_copy);
498 		va_end(ap_copy);
499 
500 		if (result < 0) {
501 			return -1;
502 		}
503 
504 		len = (size_t)result;
505 		if (len <= capacity) {
506 			s->s_len += (int)len;
507 			return 0;
508 		}
509 	} while (-1 != sbuf_ensure_capacity(s, len));
510 
511 	SBUF_SETFLAG(s, SBUF_OVERFLOWED);
512 	return -1;
513 }
514 
515 /*!
516  * @function sbuf_printf
517  *
518  * @brief
519  * Formatted-print into an sbuf using variadic arguments.
520  *
521  * @param s
522  * The sbuf.
523  *
524  * @param fmt
525  * The format string.
526  *
527  * @returns
528  * 0 on success, -1 on failure.  Always fails if the sbuf is marked as
529  * overflowed.
530  */
531 int
sbuf_printf(struct sbuf * s,const char * fmt,...)532 sbuf_printf(struct sbuf *s, const char *fmt, ...)
533 {
534 	va_list ap;
535 	int result;
536 
537 	va_start(ap, fmt);
538 	result = sbuf_vprintf(s, fmt, ap);
539 	va_end(ap);
540 	return result;
541 }
542 
543 /*!
544  * @function sbuf_putc
545  *
546  * @brief
547  * Append a single character to an sbuf.  Ignores '\0'.
548  *
549  * @param s
550  * The sbuf.
551  *
552  * @param c_
553  * The character to append.
554  *
555  * @returns
556  * 0 on success, -1 on failure.  This function will always fail if the sbuf is
557  * marked as overflowed.
558  */
559 int
sbuf_putc(struct sbuf * s,int c_)560 sbuf_putc(struct sbuf *s, int c_)
561 {
562 	char c = (char)c_;
563 
564 	if (SBUF_HASOVERFLOWED(s)) {
565 		return -1;
566 	}
567 
568 	if (-1 == sbuf_ensure_capacity(s, 1)) {
569 		SBUF_SETFLAG(s, SBUF_OVERFLOWED);
570 		return -1;
571 	}
572 
573 	if (c != '\0') {
574 		s->s_buf[s->s_len++] = c;
575 	}
576 
577 	return 0;
578 }
579 
580 static inline int
isspace(char ch)581 isspace(char ch)
582 {
583 	return ch == ' ' || ch == '\n' || ch == '\t';
584 }
585 
586 /*!
587  * @function sbuf_trim
588  *
589  * @brief
590  * Removes whitespace from the end of an sbuf.
591  *
592  * @param s
593  * The sbuf.
594  *
595  * @returns
596  * 0 on success or -1 if the sbuf is marked as overflowed.
597  */
598 int
sbuf_trim(struct sbuf * s)599 sbuf_trim(struct sbuf *s)
600 {
601 	if (SBUF_HASOVERFLOWED(s)) {
602 		return -1;
603 	}
604 
605 	while (s->s_len > 0 && isspace(s->s_buf[s->s_len - 1])) {
606 		--s->s_len;
607 	}
608 
609 	return 0;
610 }
611 
612 /*!
613  * @function sbuf_overflowed
614  *
615  * @brief
616  * Indicates whether the sbuf is marked as overflowed.
617  *
618  * @param s
619  * The sbuf.
620  *
621  * @returns
622  * 1 if the sbuf has overflowed or 0 otherwise.
623  */
624 int
sbuf_overflowed(struct sbuf * s)625 sbuf_overflowed(struct sbuf *s)
626 {
627 	return !!SBUF_HASOVERFLOWED(s);
628 }
629 
630 /*!
631  * @function sbuf_finish
632  *
633  * @brief
634  * Puts a trailing nul byte onto the sbuf data.
635  *
636  * @param s
637  * The sbuf.
638  */
639 void
sbuf_finish(struct sbuf * s)640 sbuf_finish(struct sbuf *s)
641 {
642 	/* safe because we always reserve a byte at the end for \0: */
643 	s->s_buf[s->s_len] = '\0';
644 	SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
645 	SBUF_SETFLAG(s, SBUF_FINISHED);
646 }
647 
648 /*!
649  * @function sbuf_data
650  *
651  * @brief
652  * Gets a pointer to the sbuf backing data.
653  *
654  * @param s
655  * The sbuf.
656  *
657  * @returns
658  * A pointer to the sbuf data.
659  */
660 char *
sbuf_data(struct sbuf * s)661 sbuf_data(struct sbuf *s)
662 {
663 	return s->s_buf;
664 }
665 
666 /*!
667  * @function sbuf_len
668  *
669  * @brief
670  * Retrieves the current length of the sbuf data.
671  *
672  * @param s
673  * The sbuf
674  *
675  * @returns
676  * The length of the sbuf data or -1 if the sbuf is marked as overflowed.
677  */
678 int
sbuf_len(struct sbuf * s)679 sbuf_len(struct sbuf *s)
680 {
681 	if (SBUF_HASOVERFLOWED(s)) {
682 		return -1;
683 	}
684 
685 	return s->s_len;
686 }
687 
688 /*!
689  * @function sbuf_done
690  *
691  * @brief
692  * Tests if the sbuf is marked as finished.
693  *
694  * @param s
695  * The sbuf.
696  *
697  * @returns
698  * 1 if the sbuf is marked as finished or 0 if not.
699  */
700 int
sbuf_done(struct sbuf * s)701 sbuf_done(struct sbuf *s)
702 {
703 	return !!SBUF_ISFINISHED(s);
704 }
705 
706 #if DEBUG || DEVELOPMENT
707 
708 /*
709  * a = assertion string
710  */
711 #define SBUF_FAIL(a)                                                             \
712     MACRO_BEGIN                                                                  \
713 	printf("sbuf_tests: failed assertion: %s\n", a);                         \
714 	if (what != NULL && should != NULL) {                                    \
715 	    printf("sbuf_tests: while testing: %s should %s\n", what, should);   \
716 	}                                                                        \
717 	goto fail;                                                               \
718     MACRO_END
719 
720 #define SBUF_PASS \
721     ++passed
722 
723 /*
724  * x = expression
725  */
726 #define SBUF_ASSERT(x)     \
727     MACRO_BEGIN            \
728 	if (x) {           \
729 	    SBUF_PASS;     \
730 	} else {           \
731 	    SBUF_FAIL(#x); \
732 	}                  \
733     MACRO_END
734 
735 #define SBUF_ASSERT_NOT(x) \
736     SBUF_ASSERT(!(x))
737 
738 /*
739  * e = expected
740  * a = actual
741  * c = comparator
742  */
743 #define SBUF_ASSERT_CMP(e, a, c)         \
744     MACRO_BEGIN                          \
745 	if ((a) c (e)) {                 \
746 	    SBUF_PASS;                   \
747 	} else {                         \
748 	    SBUF_FAIL(#a " " #c " " #e); \
749 	}                                \
750     MACRO_END
751 
752 #define SBUF_ASSERT_EQ(e, a)    SBUF_ASSERT_CMP(e, a, ==)
753 #define SBUF_ASSERT_NE(e, a)    SBUF_ASSERT_CMP(e, a, !=)
754 #define SBUF_ASSERT_GT(e, a)    SBUF_ASSERT_CMP(e, a, >)
755 #define SBUF_ASSERT_GTE(e, a)   SBUF_ASSERT_CMP(e, a, >=)
756 #define SBUF_ASSERT_LT(e, a)    SBUF_ASSERT_CMP(e, a, <)
757 #define SBUF_ASSERT_LTE(e, a)   SBUF_ASSERT_CMP(e, a, <=)
758 
759 #define SBUF_TEST_BEGIN      \
760     size_t passed = 0;       \
761     const char *what = NULL; \
762     const char *should = NULL;
763 
764 /*
765  * include the trailing semi-colons here intentionally to allow for block-like
766  * appearance:
767  */
768 #define SBUF_TESTING(f) \
769     MACRO_BEGIN         \
770 	what = (f);     \
771     MACRO_END;
772 
773 #define SBUF_SHOULD(s) \
774     MACRO_BEGIN        \
775 	should = (s);  \
776     MACRO_END;
777 
778 #define SBUF_TEST_END                                      \
779     printf("sbuf_tests: %zu assertions passed\n", passed); \
780     return 0;                                              \
781 fail:                                                      \
782     return ENOTRECOVERABLE;
783 
784 static int
785 sysctl_sbuf_tests SYSCTL_HANDLER_ARGS
786 {
787 #pragma unused(arg1, arg2)
788 	int rval = 0;
789 	char str[32] = { 'o', 'k', 0 };
790 
791 	rval = sysctl_handle_string(oidp, str, sizeof(str), req);
792 	if (rval != 0 || req->newptr == 0 || req->newlen < 1) {
793 		return rval;
794 	}
795 
796 	SBUF_TEST_BEGIN;
797 
798 	SBUF_TESTING("sbuf_new")
799 	{
800 		SBUF_SHOULD("fail to allocate >INT_MAX")
801 		{
802 			struct sbuf *s = NULL;
803 
804 			s = sbuf_new(NULL, NULL, INT_MIN, 0);
805 			SBUF_ASSERT_EQ(NULL, s);
806 		}
807 
808 		SBUF_SHOULD("fail when claiming a backing buffer >INT_MAX")
809 		{
810 			struct sbuf *s = NULL;
811 			char buf[4] = { 0 };
812 
813 			s = sbuf_new(NULL, buf, INT_MIN, 0);
814 			SBUF_ASSERT_EQ(NULL, s);
815 		}
816 
817 		SBUF_SHOULD("fail to allocate a zero-length sbuf")
818 		{
819 			struct sbuf *s = NULL;
820 
821 			s = sbuf_new(NULL, NULL, 0, 0);
822 			SBUF_ASSERT_EQ(NULL, s);
823 		}
824 
825 		SBUF_SHOULD("not accept invalid flags")
826 		{
827 			struct sbuf *s = NULL;
828 
829 			s = sbuf_new(NULL, NULL, 16, 0x10000);
830 			SBUF_ASSERT_EQ(NULL, s);
831 		}
832 
833 		SBUF_SHOULD("succeed when passed an existing sbuf")
834 		{
835 			struct sbuf *s = NULL;
836 			struct sbuf existing;
837 
838 			memset(&existing, 0x41, sizeof(existing));
839 			s = sbuf_new(&existing, NULL, 16, SBUF_AUTOEXTEND);
840 			SBUF_ASSERT_EQ(&existing, s);
841 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_AUTOEXTEND));
842 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNAMIC));
843 			SBUF_ASSERT_NE(NULL, s->s_buf);
844 			SBUF_ASSERT_NE(0, s->s_size);
845 			SBUF_ASSERT_EQ(0, s->s_len);
846 
847 			sbuf_delete(s);
848 		}
849 
850 		SBUF_SHOULD("succeed when passed an existing sbuf and buffer")
851 		{
852 			struct sbuf *s = NULL;
853 			struct sbuf existing;
854 			char buf[4] = { 0 };
855 
856 			memset(&existing, 0x41, sizeof(existing));
857 			s = sbuf_new(&existing, buf, sizeof(buf), 0);
858 			SBUF_ASSERT_EQ(&existing, s);
859 			SBUF_ASSERT_EQ(buf, s->s_buf);
860 			SBUF_ASSERT_EQ(4, s->s_size);
861 			SBUF_ASSERT_EQ(0, s->s_len);
862 
863 			sbuf_delete(s);
864 		}
865 
866 		SBUF_SHOULD("succeed without an existing sbuf or buffer")
867 		{
868 			struct sbuf *s = NULL;
869 
870 			s = sbuf_new(NULL, NULL, 16, 0);
871 			SBUF_ASSERT_NE(NULL, s);
872 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNAMIC));
873 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNSTRUCT));
874 			SBUF_ASSERT_NE(NULL, s->s_buf);
875 			SBUF_ASSERT_NE(0, s->s_size);
876 			SBUF_ASSERT_EQ(0, s->s_len);
877 
878 			sbuf_delete(s);
879 		}
880 
881 		SBUF_SHOULD("succeed without an existing sbuf, but with a buffer")
882 		{
883 			struct sbuf *s = NULL;
884 			char buf[4] = { 0 };
885 
886 			s = sbuf_new(NULL, buf, sizeof(buf), 0);
887 			SBUF_ASSERT_NE(NULL, s);
888 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNSTRUCT));
889 			SBUF_ASSERT_EQ(buf, s->s_buf);
890 			SBUF_ASSERT_EQ(4, s->s_size);
891 			SBUF_ASSERT_EQ(0, s->s_len);
892 
893 			sbuf_delete(s);
894 		}
895 
896 		SBUF_SHOULD("round up the requested size if SBUF_AUTOEXTEND")
897 		{
898 			struct sbuf *s = NULL;
899 
900 			s = sbuf_new(NULL, NULL, 1, SBUF_AUTOEXTEND);
901 			SBUF_ASSERT_GT(1, s->s_size);
902 
903 			sbuf_delete(s);
904 		}
905 	}
906 
907 	SBUF_TESTING("sbuf_clear")
908 	{
909 		SBUF_SHOULD("clear the overflowed and finished flags")
910 		{
911 			struct sbuf *s = NULL;
912 
913 			s = sbuf_new(NULL, NULL, 16, 0);
914 
915 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
916 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
917 			SBUF_SETFLAG(s, SBUF_FINISHED);
918 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_FINISHED));
919 			sbuf_clear(s);
920 			SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
921 			SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_FINISHED));
922 
923 			sbuf_delete(s);
924 		}
925 
926 		SBUF_SHOULD("reset the position to zero")
927 		{
928 			struct sbuf *s = NULL;
929 
930 			s = sbuf_new(NULL, NULL, 16, 0);
931 
932 			s->s_len = 1;
933 			sbuf_clear(s);
934 			SBUF_ASSERT_EQ(0, s->s_len);
935 
936 			sbuf_delete(s);
937 		}
938 	}
939 
940 	SBUF_TESTING("sbuf_extend")
941 	{
942 		SBUF_SHOULD("allow zero")
943 		{
944 			struct sbuf *s = NULL;
945 			int size_before;
946 
947 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
948 			size_before = s->s_size;
949 			SBUF_ASSERT_EQ(0, sbuf_extend(s, 0));
950 			SBUF_ASSERT_EQ(size_before, s->s_size);
951 
952 			sbuf_delete(s);
953 		}
954 
955 		SBUF_SHOULD("fail for sbuf not marked as SBUF_AUTOEXTEND")
956 		{
957 			struct sbuf *s = NULL;
958 
959 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
960 			SBUF_ASSERT_EQ(-1, sbuf_extend(s, 10));
961 
962 			sbuf_delete(s);
963 		}
964 
965 		SBUF_SHOULD("accommodate reasonable requests")
966 		{
967 			struct sbuf *s = NULL;
968 			int size_before;
969 
970 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
971 			size_before = s->s_size;
972 
973 			SBUF_ASSERT_EQ(0, sbuf_extend(s, 10));
974 			SBUF_ASSERT_GTE(10, s->s_size - size_before);
975 
976 			sbuf_delete(s);
977 		}
978 
979 		SBUF_SHOULD("reject requests that cause overflows")
980 		{
981 			struct sbuf *s = NULL;
982 
983 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
984 			SBUF_ASSERT_EQ(-1, sbuf_extend(s, SIZE_MAX));
985 			SBUF_ASSERT_EQ(-1, sbuf_extend(s, INT_MAX));
986 
987 			sbuf_delete(s);
988 		}
989 
990 		SBUF_SHOULD("transform the sbuf into an SBUF_DYNAMIC one")
991 		{
992 			struct sbuf *s = NULL;
993 			char buf[4] = { 0 };
994 
995 			s = sbuf_new(NULL, buf, sizeof(buf), SBUF_AUTOEXTEND);
996 			SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_DYNAMIC));
997 			SBUF_ASSERT_EQ(0, sbuf_extend(s, 10));
998 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNAMIC));
999 
1000 			sbuf_delete(s);
1001 		}
1002 	}
1003 
1004 	SBUF_TESTING("sbuf_capacity")
1005 	{
1006 		SBUF_SHOULD("account for the trailing nul byte")
1007 		{
1008 			struct sbuf *s = NULL;
1009 
1010 			s = sbuf_new(NULL, NULL, 16, 0);
1011 			SBUF_ASSERT_EQ(s->s_size - s->s_len - 1, sbuf_capacity(s));
1012 
1013 			sbuf_delete(s);
1014 		}
1015 	}
1016 
1017 	SBUF_TESTING("sbuf_ensure_capacity")
1018 	{
1019 		SBUF_SHOULD("return 0 if the sbuf already has enough capacity")
1020 		{
1021 			struct sbuf *s = NULL;
1022 			int size_before;
1023 
1024 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1025 			size_before = s->s_size;
1026 			SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s, 5));
1027 			SBUF_ASSERT_EQ(size_before, s->s_size);
1028 
1029 			sbuf_delete(s);
1030 		}
1031 
1032 		SBUF_SHOULD("extend the buffer as needed")
1033 		{
1034 			struct sbuf *s = NULL;
1035 			int size_before;
1036 
1037 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1038 			size_before = s->s_size;
1039 			SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s, 30));
1040 			SBUF_ASSERT_GT(size_before, s->s_size);
1041 
1042 			sbuf_delete(s);
1043 		}
1044 	}
1045 
1046 	SBUF_TESTING("sbuf_bcat")
1047 	{
1048 		SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1049 		{
1050 			struct sbuf *s = NULL;
1051 
1052 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1053 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1054 			SBUF_ASSERT_EQ(-1, sbuf_bcat(s, "A", 1));
1055 
1056 			sbuf_delete(s);
1057 		}
1058 
1059 		SBUF_SHOULD("fail if len is too big")
1060 		{
1061 			struct sbuf *s = NULL;
1062 
1063 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1064 			SBUF_ASSERT_EQ(-1, sbuf_bcat(s, "A", INT_MAX));
1065 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1066 
1067 			sbuf_delete(s);
1068 		}
1069 
1070 		SBUF_SHOULD("succeed for a fixed buf within limits")
1071 		{
1072 			struct sbuf *s = NULL;
1073 
1074 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1075 			SBUF_ASSERT_EQ(0, sbuf_bcat(s, "ABC", 3));
1076 			SBUF_ASSERT_EQ(3, s->s_len);
1077 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1078 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1079 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1080 
1081 			sbuf_delete(s);
1082 		}
1083 
1084 		SBUF_SHOULD("succeed for binary data, even with nul bytes")
1085 		{
1086 			struct sbuf *s = NULL;
1087 
1088 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1089 			SBUF_ASSERT_EQ(0, sbuf_bcat(s, "A\0C", 3));
1090 			SBUF_ASSERT_EQ(3, s->s_len);
1091 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1092 			SBUF_ASSERT_EQ('\0', s->s_buf[1]);
1093 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1094 
1095 			sbuf_delete(s);
1096 		}
1097 
1098 		SBUF_SHOULD("append to existing data")
1099 		{
1100 			struct sbuf *s = NULL;
1101 
1102 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1103 			SBUF_ASSERT_EQ(0, sbuf_bcat(s, "ABC", 3));
1104 			SBUF_ASSERT_EQ(3, s->s_len);
1105 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1106 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1107 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1108 
1109 			SBUF_ASSERT_EQ(0, sbuf_bcat(s, "DEF", 3));
1110 			SBUF_ASSERT_EQ(6, s->s_len);
1111 			SBUF_ASSERT_EQ('D', s->s_buf[3]);
1112 			SBUF_ASSERT_EQ('E', s->s_buf[4]);
1113 			SBUF_ASSERT_EQ('F', s->s_buf[5]);
1114 
1115 			sbuf_delete(s);
1116 		}
1117 
1118 		SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1119 		{
1120 			struct sbuf *s = NULL;
1121 
1122 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1123 			SBUF_ASSERT_EQ(0, sbuf_bcat(s, "0123456789abcde", 15));
1124 			SBUF_ASSERT_EQ(15, s->s_len);
1125 
1126 			sbuf_delete(s);
1127 		}
1128 
1129 		SBUF_SHOULD("fail for a fixed buf if too big")
1130 		{
1131 			struct sbuf *s = NULL;
1132 
1133 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1134 			SBUF_ASSERT_EQ(-1, sbuf_bcat(s, "0123456789abcdef", 16));
1135 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1136 
1137 			sbuf_delete(s);
1138 		}
1139 
1140 		SBUF_SHOULD("expand the backing buffer as needed")
1141 		{
1142 			struct sbuf *s = NULL;
1143 			int size_before;
1144 
1145 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1146 			size_before = s->s_size;
1147 			SBUF_ASSERT_EQ(0, sbuf_bcat(s, "0123456789abcdef", 16));
1148 			SBUF_ASSERT_GT(size_before, s->s_size);
1149 			SBUF_ASSERT_EQ(16, s->s_len);
1150 
1151 			sbuf_delete(s);
1152 		}
1153 	}
1154 
1155 	SBUF_TESTING("sbuf_bcpy")
1156 	{
1157 		SBUF_SHOULD("overwrite any existing data")
1158 		{
1159 			struct sbuf *s = NULL;
1160 
1161 			s = sbuf_new(NULL, NULL, 16, 0);
1162 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "ABC", 3));
1163 			SBUF_ASSERT_EQ(3, s->s_len);
1164 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1165 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1166 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1167 
1168 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "XYZ123", 6));
1169 			SBUF_ASSERT_EQ(6, s->s_len);
1170 			SBUF_ASSERT_EQ('X', s->s_buf[0]);
1171 			SBUF_ASSERT_EQ('Y', s->s_buf[1]);
1172 			SBUF_ASSERT_EQ('Z', s->s_buf[2]);
1173 			SBUF_ASSERT_EQ('1', s->s_buf[3]);
1174 			SBUF_ASSERT_EQ('2', s->s_buf[4]);
1175 			SBUF_ASSERT_EQ('3', s->s_buf[5]);
1176 
1177 			sbuf_delete(s);
1178 		}
1179 
1180 		SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space")
1181 		{
1182 			struct sbuf *s = NULL;
1183 
1184 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1185 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1186 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "A", 1));
1187 
1188 			sbuf_delete(s);
1189 		}
1190 
1191 		SBUF_SHOULD("fail if len is too big")
1192 		{
1193 			struct sbuf *s = NULL;
1194 
1195 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1196 			SBUF_ASSERT_EQ(-1, sbuf_bcpy(s, "A", INT_MAX));
1197 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1198 
1199 			sbuf_delete(s);
1200 		}
1201 
1202 		SBUF_SHOULD("succeed for a fixed buf within limits")
1203 		{
1204 			struct sbuf *s = NULL;
1205 
1206 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1207 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "ABC", 3));
1208 			SBUF_ASSERT_EQ(3, s->s_len);
1209 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1210 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1211 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1212 
1213 			sbuf_delete(s);
1214 		}
1215 
1216 		SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1217 		{
1218 			struct sbuf *s = NULL;
1219 
1220 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1221 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "0123456789abcde", 15));
1222 			SBUF_ASSERT_EQ(15, s->s_len);
1223 
1224 			sbuf_delete(s);
1225 		}
1226 
1227 		SBUF_SHOULD("fail for a fixed buf if too big")
1228 		{
1229 			struct sbuf *s = NULL;
1230 
1231 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1232 			SBUF_ASSERT_EQ(-1, sbuf_bcpy(s, "0123456789abcdef", 16));
1233 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1234 
1235 			sbuf_delete(s);
1236 		}
1237 
1238 		SBUF_SHOULD("expand the backing buffer as needed")
1239 		{
1240 			struct sbuf *s = NULL;
1241 			int size_before;
1242 
1243 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1244 			size_before = s->s_size;
1245 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "0123456789abcdef", 16));
1246 			SBUF_ASSERT_GT(size_before, s->s_size);
1247 			SBUF_ASSERT_EQ(16, s->s_len);
1248 
1249 			sbuf_delete(s);
1250 		}
1251 	}
1252 
1253 	SBUF_TESTING("sbuf_cat")
1254 	{
1255 		SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1256 		{
1257 			struct sbuf *s = NULL;
1258 
1259 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1260 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1261 			SBUF_ASSERT_EQ(-1, sbuf_cat(s, "A"));
1262 
1263 			sbuf_delete(s);
1264 		}
1265 
1266 		SBUF_SHOULD("succeed for a fixed buf within limits")
1267 		{
1268 			struct sbuf *s = NULL;
1269 
1270 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1271 			SBUF_ASSERT_EQ(0, sbuf_cat(s, "ABC"));
1272 			SBUF_ASSERT_EQ(3, s->s_len);
1273 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1274 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1275 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1276 
1277 			sbuf_delete(s);
1278 		}
1279 
1280 		SBUF_SHOULD("only copy up to a nul byte")
1281 		{
1282 			struct sbuf *s = NULL;
1283 
1284 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1285 			SBUF_ASSERT_EQ(0, sbuf_cat(s, "A\0C"));
1286 			SBUF_ASSERT_EQ(1, s->s_len);
1287 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1288 
1289 			sbuf_delete(s);
1290 		}
1291 
1292 		SBUF_SHOULD("append to existing data")
1293 		{
1294 			struct sbuf *s = NULL;
1295 
1296 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1297 			SBUF_ASSERT_EQ(0, sbuf_cat(s, "ABC"));
1298 			SBUF_ASSERT_EQ(3, s->s_len);
1299 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1300 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1301 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1302 
1303 			SBUF_ASSERT_EQ(0, sbuf_cat(s, "DEF"));
1304 			SBUF_ASSERT_EQ(6, s->s_len);
1305 			SBUF_ASSERT_EQ('D', s->s_buf[3]);
1306 			SBUF_ASSERT_EQ('E', s->s_buf[4]);
1307 			SBUF_ASSERT_EQ('F', s->s_buf[5]);
1308 
1309 			sbuf_delete(s);
1310 		}
1311 
1312 		SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1313 		{
1314 			struct sbuf *s = NULL;
1315 
1316 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1317 			SBUF_ASSERT_EQ(0, sbuf_cat(s, "0123456789abcde"));
1318 			SBUF_ASSERT_EQ(15, s->s_len);
1319 
1320 			sbuf_delete(s);
1321 		}
1322 
1323 		SBUF_SHOULD("fail for a fixed buf if too big")
1324 		{
1325 			struct sbuf *s = NULL;
1326 
1327 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1328 			SBUF_ASSERT_EQ(-1, sbuf_cat(s, "0123456789abcdef"));
1329 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1330 
1331 			sbuf_delete(s);
1332 		}
1333 
1334 		SBUF_SHOULD("expand the backing buffer as needed")
1335 		{
1336 			struct sbuf *s = NULL;
1337 			int size_before;
1338 
1339 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1340 			size_before = s->s_size;
1341 			SBUF_ASSERT_EQ(0, sbuf_cat(s, "0123456789abcdef"));
1342 			SBUF_ASSERT_GT(size_before, s->s_size);
1343 			SBUF_ASSERT_EQ(16, s->s_len);
1344 
1345 			sbuf_delete(s);
1346 		}
1347 	}
1348 
1349 	SBUF_TESTING("sbuf_cpy")
1350 	{
1351 		SBUF_SHOULD("overwrite any existing data")
1352 		{
1353 			struct sbuf *s = NULL;
1354 
1355 			s = sbuf_new(NULL, NULL, 16, 0);
1356 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "ABC"));
1357 			SBUF_ASSERT_EQ(3, s->s_len);
1358 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1359 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1360 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1361 
1362 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "XYZ123"));
1363 			SBUF_ASSERT_EQ(6, s->s_len);
1364 			SBUF_ASSERT_EQ('X', s->s_buf[0]);
1365 			SBUF_ASSERT_EQ('Y', s->s_buf[1]);
1366 			SBUF_ASSERT_EQ('Z', s->s_buf[2]);
1367 			SBUF_ASSERT_EQ('1', s->s_buf[3]);
1368 			SBUF_ASSERT_EQ('2', s->s_buf[4]);
1369 			SBUF_ASSERT_EQ('3', s->s_buf[5]);
1370 
1371 			sbuf_delete(s);
1372 		}
1373 
1374 		SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space")
1375 		{
1376 			struct sbuf *s = NULL;
1377 
1378 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1379 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1380 			SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "A", 1));
1381 
1382 			sbuf_delete(s);
1383 		}
1384 
1385 		SBUF_SHOULD("succeed for a fixed buf within limits")
1386 		{
1387 			struct sbuf *s = NULL;
1388 
1389 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1390 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "ABC"));
1391 			SBUF_ASSERT_EQ(3, s->s_len);
1392 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1393 			SBUF_ASSERT_EQ('B', s->s_buf[1]);
1394 			SBUF_ASSERT_EQ('C', s->s_buf[2]);
1395 
1396 			sbuf_delete(s);
1397 		}
1398 
1399 		SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1400 		{
1401 			struct sbuf *s = NULL;
1402 
1403 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1404 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
1405 			SBUF_ASSERT_EQ(15, s->s_len);
1406 
1407 			sbuf_delete(s);
1408 		}
1409 
1410 		SBUF_SHOULD("fail for a fixed buf if too big")
1411 		{
1412 			struct sbuf *s = NULL;
1413 
1414 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1415 			SBUF_ASSERT_EQ(-1, sbuf_cpy(s, "0123456789abcdef"));
1416 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1417 
1418 			sbuf_delete(s);
1419 		}
1420 
1421 		SBUF_SHOULD("expand the backing buffer as needed")
1422 		{
1423 			struct sbuf *s = NULL;
1424 			int size_before;
1425 
1426 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1427 			size_before = s->s_size;
1428 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcdef"));
1429 			SBUF_ASSERT_GT(size_before, s->s_size);
1430 			SBUF_ASSERT_EQ(16, s->s_len);
1431 
1432 			sbuf_delete(s);
1433 		}
1434 	}
1435 
1436 	/* also tests sbuf_vprintf: */
1437 	SBUF_TESTING("sbuf_printf")
1438 	{
1439 		SBUF_SHOULD("support simple printing")
1440 		{
1441 			struct sbuf *s = NULL;
1442 
1443 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1444 			SBUF_ASSERT_EQ(0, sbuf_printf(s, "hello"));
1445 			SBUF_ASSERT_EQ(5, s->s_len);
1446 			SBUF_ASSERT_EQ('h', s->s_buf[0]);
1447 			SBUF_ASSERT_EQ('e', s->s_buf[1]);
1448 			SBUF_ASSERT_EQ('l', s->s_buf[2]);
1449 			SBUF_ASSERT_EQ('l', s->s_buf[3]);
1450 			SBUF_ASSERT_EQ('o', s->s_buf[4]);
1451 
1452 			sbuf_delete(s);
1453 		}
1454 
1455 		SBUF_SHOULD("support format strings")
1456 		{
1457 			struct sbuf *s = NULL;
1458 			char data1 = 'A';
1459 			int data2 = 123;
1460 			const char *data3 = "foo";
1461 
1462 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1463 			SBUF_ASSERT_EQ(0, sbuf_printf(s, "%c %d %s", data1, data2, data3));
1464 			SBUF_ASSERT_EQ(9, s->s_len);
1465 			SBUF_ASSERT_EQ('A', s->s_buf[0]);
1466 			SBUF_ASSERT_EQ(' ', s->s_buf[1]);
1467 			SBUF_ASSERT_EQ('1', s->s_buf[2]);
1468 			SBUF_ASSERT_EQ('2', s->s_buf[3]);
1469 			SBUF_ASSERT_EQ('3', s->s_buf[4]);
1470 			SBUF_ASSERT_EQ(' ', s->s_buf[5]);
1471 			SBUF_ASSERT_EQ('f', s->s_buf[6]);
1472 			SBUF_ASSERT_EQ('o', s->s_buf[7]);
1473 			SBUF_ASSERT_EQ('o', s->s_buf[8]);
1474 
1475 			sbuf_delete(s);
1476 		}
1477 
1478 		SBUF_SHOULD("work with the fact we reserve a nul byte at the end")
1479 		{
1480 			struct sbuf *s = NULL;
1481 
1482 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1483 			SBUF_ASSERT_EQ(0, sbuf_printf(s, "0123456789abcde"));
1484 			SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1485 
1486 			sbuf_delete(s);
1487 		}
1488 
1489 		SBUF_SHOULD("mark the sbuf as overflowed if we try to write too much")
1490 		{
1491 			struct sbuf *s = NULL;
1492 
1493 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1494 			SBUF_ASSERT_EQ(-1, sbuf_printf(s, "0123456789abcdef"));
1495 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1496 
1497 			sbuf_delete(s);
1498 		}
1499 
1500 		SBUF_SHOULD("auto-extend as necessary")
1501 		{
1502 			struct sbuf *s = NULL;
1503 			const char *data = "0123456789abcdef";
1504 			int size_before;
1505 			size_t n;
1506 
1507 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1508 			size_before = s->s_size;
1509 			SBUF_ASSERT_EQ(0, sbuf_printf(s, "%s", data));
1510 			SBUF_ASSERT_GT(size_before, s->s_size);
1511 
1512 			for (n = 0; n < strlen(data); ++n) {
1513 				SBUF_ASSERT_EQ(data[n], s->s_buf[n]);
1514 			}
1515 
1516 			sbuf_delete(s);
1517 		}
1518 
1519 		SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1520 		{
1521 			struct sbuf *s = NULL;
1522 
1523 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1524 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1525 			SBUF_ASSERT_EQ(-1, sbuf_printf(s, "A"));
1526 
1527 			sbuf_delete(s);
1528 		}
1529 	}
1530 
1531 	SBUF_TESTING("sbuf_putc")
1532 	{
1533 		SBUF_SHOULD("work where we have capacity")
1534 		{
1535 			struct sbuf *s = NULL;
1536 
1537 			s = sbuf_new(NULL, NULL, 16, 0);
1538 			SBUF_ASSERT_EQ(0, sbuf_putc(s, 'a'));
1539 			SBUF_ASSERT_EQ(1, s->s_len);
1540 			SBUF_ASSERT_EQ('a', s->s_buf[0]);
1541 
1542 			sbuf_delete(s);
1543 		}
1544 
1545 		SBUF_SHOULD("fail if we have a full, fixedlen sbuf")
1546 		{
1547 			struct sbuf *s = NULL;
1548 
1549 			s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1550 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcd"));
1551 			SBUF_ASSERT_EQ(0, sbuf_putc(s, 'e'));
1552 			SBUF_ASSERT_EQ(-1, sbuf_putc(s, 'f'));
1553 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1554 
1555 			sbuf_delete(s);
1556 		}
1557 
1558 		SBUF_SHOULD("ignore nul")
1559 		{
1560 			struct sbuf *s = NULL;
1561 
1562 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1563 			SBUF_ASSERT_EQ(0, sbuf_putc(s, '\0'));
1564 			SBUF_ASSERT_EQ(0, s->s_len);
1565 
1566 			sbuf_delete(s);
1567 		}
1568 
1569 		SBUF_SHOULD("auto-extend if necessary")
1570 		{
1571 			struct sbuf *s = NULL;
1572 			int len_before;
1573 			int size_before;
1574 
1575 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1576 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
1577 			len_before = s->s_len;
1578 			size_before = s->s_size;
1579 			SBUF_ASSERT_EQ(0, sbuf_putc(s, 'f'));
1580 			SBUF_ASSERT_EQ(len_before + 1, s->s_len);
1581 			SBUF_ASSERT_GT(size_before, s->s_size);
1582 			SBUF_ASSERT_EQ('f', s->s_buf[s->s_len - 1]);
1583 
1584 			sbuf_delete(s);
1585 		}
1586 
1587 		SBUF_SHOULD("fail if the sbuf is overflowed")
1588 		{
1589 			struct sbuf *s = NULL;
1590 
1591 			s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1592 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1593 			SBUF_ASSERT_EQ(-1, sbuf_putc(s, 'a'));
1594 
1595 			sbuf_delete(s);
1596 		}
1597 	}
1598 
1599 	SBUF_TESTING("sbuf_trim")
1600 	{
1601 		SBUF_SHOULD("remove trailing spaces, tabs and newlines")
1602 		{
1603 			struct sbuf *s = NULL;
1604 			const char *test = "foo    \t\t\n\t";
1605 
1606 			s = sbuf_new(NULL, NULL, 16, 0);
1607 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, test));
1608 			SBUF_ASSERT_EQ(strlen(test), s->s_len);
1609 			SBUF_ASSERT_EQ(0, sbuf_trim(s));
1610 			SBUF_ASSERT_EQ(3, s->s_len);
1611 
1612 			sbuf_delete(s);
1613 		}
1614 
1615 		SBUF_SHOULD("do nothing if there is no trailing whitespace")
1616 		{
1617 			struct sbuf *s = NULL;
1618 			const char *test = "foo";
1619 
1620 			s = sbuf_new(NULL, NULL, 16, 0);
1621 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, test));
1622 			SBUF_ASSERT_EQ(strlen(test), s->s_len);
1623 			SBUF_ASSERT_EQ(0, sbuf_trim(s));
1624 			SBUF_ASSERT_EQ(strlen(test), s->s_len);
1625 
1626 			sbuf_delete(s);
1627 		}
1628 
1629 		SBUF_SHOULD("fail if the sbuf is overflowed")
1630 		{
1631 			struct sbuf *s = NULL;
1632 			const char *test = "foo   ";
1633 
1634 			s = sbuf_new(NULL, NULL, 16, 0);
1635 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, test));
1636 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1637 			SBUF_ASSERT_EQ(-1, sbuf_trim(s));
1638 			SBUF_ASSERT_EQ(strlen(test), s->s_len);
1639 
1640 			sbuf_delete(s);
1641 		}
1642 
1643 		SBUF_SHOULD("work on empty strings")
1644 		{
1645 			struct sbuf *s = NULL;
1646 
1647 			s = sbuf_new(NULL, NULL, 16, 0);
1648 			SBUF_ASSERT_EQ(0, sbuf_trim(s));
1649 			SBUF_ASSERT_EQ(0, s->s_len);
1650 
1651 			sbuf_delete(s);
1652 		}
1653 	}
1654 
1655 	SBUF_TESTING("sbuf_overflowed")
1656 	{
1657 		SBUF_SHOULD("return false if it hasn't overflowed")
1658 		{
1659 			struct sbuf *s = NULL;
1660 
1661 			s = sbuf_new(NULL, NULL, 16, 0);
1662 			SBUF_ASSERT_NOT(sbuf_overflowed(s));
1663 
1664 			sbuf_delete(s);
1665 		}
1666 
1667 		SBUF_SHOULD("return true if it has overflowed")
1668 		{
1669 			struct sbuf *s = NULL;
1670 
1671 			s = sbuf_new(NULL, NULL, 16, 0);
1672 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1673 			SBUF_ASSERT(sbuf_overflowed(s));
1674 
1675 			sbuf_delete(s);
1676 		}
1677 	}
1678 
1679 	SBUF_TESTING("sbuf_finish")
1680 	{
1681 		SBUF_SHOULD("insert a nul byte, clear the overflowed flag and set the finished flag")
1682 		{
1683 			struct sbuf *s = NULL;
1684 
1685 			s = sbuf_new(NULL, NULL, 16, 0);
1686 			SBUF_ASSERT_EQ(0, sbuf_putc(s, 'A'));
1687 			s->s_buf[s->s_len] = 'x';
1688 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1689 			SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_FINISHED));
1690 
1691 			sbuf_finish(s);
1692 
1693 			SBUF_ASSERT_EQ(0, s->s_buf[s->s_len]);
1694 			SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1695 			SBUF_ASSERT(SBUF_ISSET(s, SBUF_FINISHED));
1696 
1697 			sbuf_delete(s);
1698 		}
1699 	}
1700 
1701 	SBUF_TESTING("sbuf_data")
1702 	{
1703 		SBUF_SHOULD("return the s_buf pointer")
1704 		{
1705 			struct sbuf *s = NULL;
1706 
1707 			s = sbuf_new(NULL, NULL, 16, 0);
1708 			SBUF_ASSERT_EQ(s->s_buf, sbuf_data(s));
1709 
1710 			sbuf_delete(s);
1711 		}
1712 
1713 		SBUF_SHOULD("return the buffer we gave it")
1714 		{
1715 			struct sbuf *s = NULL;
1716 			char buf[4] = { 0 };
1717 
1718 			s = sbuf_new(NULL, buf, sizeof(buf), 0);
1719 			SBUF_ASSERT_EQ(buf, sbuf_data(s));
1720 
1721 			sbuf_delete(s);
1722 		}
1723 	}
1724 
1725 	SBUF_TESTING("sbuf_len")
1726 	{
1727 		SBUF_SHOULD("return the length of the sbuf data")
1728 		{
1729 			struct sbuf *s = NULL;
1730 
1731 			s = sbuf_new(NULL, NULL, 16, 0);
1732 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "hello"));
1733 			SBUF_ASSERT_EQ(5, sbuf_len(s));
1734 
1735 			sbuf_delete(s);
1736 		}
1737 
1738 		SBUF_SHOULD("return -1 if the sbuf is overflowed")
1739 		{
1740 			struct sbuf *s = NULL;
1741 
1742 			s = sbuf_new(NULL, NULL, 16, 0);
1743 			SBUF_ASSERT_EQ(0, sbuf_cpy(s, "hello"));
1744 			SBUF_ASSERT_EQ(5, sbuf_len(s));
1745 			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1746 			SBUF_ASSERT_EQ(-1, sbuf_len(s));
1747 
1748 			sbuf_delete(s);
1749 		}
1750 	}
1751 
1752 	SBUF_TESTING("sbuf_done")
1753 	{
1754 		SBUF_SHOULD("return false if the sbuf isn't finished")
1755 		{
1756 			struct sbuf *s = NULL;
1757 
1758 			s = sbuf_new(NULL, NULL, 16, 0);
1759 			SBUF_ASSERT_NOT(sbuf_done(s));
1760 
1761 			sbuf_delete(s);
1762 		}
1763 
1764 		SBUF_SHOULD("return true if the sbuf has finished")
1765 		{
1766 			struct sbuf *s = NULL;
1767 
1768 			s = sbuf_new(NULL, NULL, 16, 0);
1769 			SBUF_ASSERT_NOT(sbuf_done(s));
1770 			SBUF_SETFLAG(s, SBUF_FINISHED);
1771 			SBUF_ASSERT(sbuf_done(s));
1772 
1773 			sbuf_delete(s);
1774 		}
1775 	}
1776 
1777 	SBUF_TESTING("sbuf_delete")
1778 	{
1779 		SBUF_SHOULD("just free the backing buffer if we supplied an sbuf")
1780 		{
1781 			struct sbuf *s = NULL;
1782 			struct sbuf existing = {};
1783 
1784 			s = sbuf_new(&existing, NULL, 16, 0);
1785 			SBUF_ASSERT_NE(NULL, s->s_buf);
1786 
1787 			sbuf_delete(s);
1788 			SBUF_ASSERT_EQ(NULL, s->s_buf);
1789 		}
1790 	}
1791 
1792 	SBUF_TEST_END;
1793 }
1794 
1795 SYSCTL_PROC(_kern, OID_AUTO, sbuf_test, CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_MASKED, 0, 0, sysctl_sbuf_tests, "A", "sbuf tests");
1796 
1797 #endif /* DEBUG || DEVELOPMENT */
1798