]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/subr_sbuf.c
xnu-7195.60.75.tar.gz
[apple/xnu.git] / bsd / kern / subr_sbuf.c
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
68 sbuf_delete(struct sbuf *s)
69 {
70 if (SBUF_ISDYNAMIC(s) && s->s_buf) {
71 kheap_free(KHEAP_DATA_BUFFERS, s->s_buf, s->s_size);
72 s->s_buf = NULL;
73 }
74
75 if (SBUF_ISDYNSTRUCT(s)) {
76 kheap_free(KHEAP_DEFAULT, s, sizeof(*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
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 *
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 *)kheap_alloc(KHEAP_DEFAULT, sizeof(*s), Z_WAITOK);
162 if (NULL == s) {
163 return NULL;
164 }
165
166 bzero(s, sizeof(*s));
167 s->s_flags = flags;
168 SBUF_SETFLAG(s, SBUF_DYNSTRUCT);
169 } else {
170 bzero(s, sizeof(*s));
171 s->s_flags = flags;
172 }
173
174 if (buf) {
175 s->s_size = (int)length;
176 s->s_buf = buf;
177 return s;
178 }
179
180 if (SBUF_CANEXTEND(s) && (-1 == sbuf_extendsize(&length))) {
181 goto fail;
182 }
183
184 /*
185 * we always need at least 1 byte for \0, so s_size of 0 will cause an
186 * underflow in sbuf_capacity.
187 */
188 if (length == 0) {
189 goto fail;
190 }
191
192 s->s_buf = (char *)kheap_alloc(KHEAP_DATA_BUFFERS, length, Z_WAITOK);
193 if (NULL == s->s_buf) {
194 goto fail;
195 }
196 bzero(s->s_buf, length);
197 s->s_size = (int)length;
198
199 SBUF_SETFLAG(s, SBUF_DYNAMIC);
200 return s;
201
202 fail:
203 sbuf_delete(s);
204 return NULL;
205 }
206
207 /*!
208 * @function sbuf_setpos
209 *
210 * @brief
211 * Set the current position of the sbuf.
212 *
213 * @param s
214 * The sbuf to modify.
215 *
216 * @param pos
217 * The new position to set. Must be less than or equal to the current position.
218 *
219 * @returns
220 * 0 on success, -1 on failure.
221 */
222 int
223 sbuf_setpos(struct sbuf *s, int pos)
224 {
225 if (pos < 0 || pos > s->s_len) {
226 return -1;
227 }
228
229 s->s_len = pos;
230 return 0;
231 }
232
233 /*!
234 * @function sbuf_clear
235 *
236 * @brief
237 * Resets the position/length of the sbuf data to zero and clears the finished
238 * and overflow flags.
239 *
240 * @param s
241 * The sbuf to clear.
242 */
243 void
244 sbuf_clear(struct sbuf *s)
245 {
246 SBUF_CLEARFLAG(s, SBUF_FINISHED);
247 SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
248 sbuf_setpos(s, 0);
249 }
250
251 /*!
252 * @function sbuf_extend
253 *
254 * @brief
255 * Attempt to extend the size of an sbuf's backing buffer by @a addlen bytes.
256 *
257 * @param s
258 * The sbuf to extend.
259 *
260 * @param addlen
261 * How many bytes to increase the size by.
262 *
263 * @returns
264 * 0 on success, -1 on failure.
265 */
266 static int OS_WARN_RESULT
267 sbuf_extend(struct sbuf *s, size_t addlen)
268 {
269 char *new_buf;
270 size_t new_size;
271
272 if (addlen == 0) {
273 return 0;
274 }
275
276 if (!SBUF_CANEXTEND(s)) {
277 return -1;
278 }
279
280 if (os_add_overflow((size_t)s->s_size, addlen, &new_size)) {
281 return -1;
282 }
283
284 if (-1 == sbuf_extendsize(&new_size)) {
285 return -1;
286 }
287
288 new_buf = (char *)kheap_alloc(KHEAP_DATA_BUFFERS, new_size, Z_WAITOK);
289 if (NULL == new_buf) {
290 return -1;
291 }
292
293 bcopy(s->s_buf, new_buf, (size_t)s->s_size);
294 if (SBUF_ISDYNAMIC(s)) {
295 kheap_free(KHEAP_DATA_BUFFERS, s->s_buf, (size_t)s->s_size);
296 } else {
297 SBUF_SETFLAG(s, SBUF_DYNAMIC);
298 }
299
300 s->s_buf = new_buf;
301 s->s_size = (int)new_size;
302 return 0;
303 }
304
305 /*!
306 * @function sbuf_capacity
307 *
308 * @brief
309 * Get the current capacity of an sbuf: how many more bytes we can append given
310 * the current size and position.
311 *
312 * @param s
313 * The sbuf to get the capacity of.
314 *
315 * @returns
316 * The current sbuf capacity.
317 */
318 static size_t
319 sbuf_capacity(const struct sbuf *s)
320 {
321 /* 1 byte reserved for \0: */
322 return (size_t)(s->s_size - s->s_len - 1);
323 }
324
325 /*!
326 * @function sbuf_ensure_capacity
327 *
328 * @brief
329 * Ensure that an sbuf can accommodate @a add_len bytes, reallocating the
330 * backing buffer if necessary.
331 *
332 * @param s
333 * The sbuf.
334 *
335 * @param wanted
336 * The minimum capacity to ensure @a s has.
337 *
338 * @returns
339 * 0 if the minimum capacity is met by @a s, or -1 on error.
340 */
341 static int
342 sbuf_ensure_capacity(struct sbuf *s, size_t wanted)
343 {
344 size_t size;
345
346 size = sbuf_capacity(s);
347 if (size >= wanted) {
348 return 0;
349 }
350
351 return sbuf_extend(s, wanted - size);
352 }
353
354 /*!
355 * @function sbuf_bcat
356 *
357 * @brief
358 * Append data to an sbuf.
359 *
360 * @param s
361 * The sbuf.
362 *
363 * @param data
364 * The data to append.
365 *
366 * @param len
367 * The length of the data.
368 *
369 * @returns
370 * 0 on success, -1 on failure. Will always fail if the sbuf is marked as
371 * overflowed.
372 */
373 int
374 sbuf_bcat(struct sbuf *s, const void *data, size_t len)
375 {
376 if (SBUF_HASOVERFLOWED(s)) {
377 return -1;
378 }
379
380 if (-1 == sbuf_ensure_capacity(s, len)) {
381 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
382 return -1;
383 }
384
385 bcopy(data, s->s_buf + s->s_len, len);
386 s->s_len += (int)len; /* safe */
387
388 return 0;
389 }
390
391 /*!
392 * @function sbuf_bcpy
393 *
394 * @brief
395 * Set the entire sbuf data, possibly reallocating the backing buffer to
396 * accommodate.
397 *
398 * @param s
399 * The sbuf.
400 *
401 * @param data
402 * The data to set.
403 *
404 * @param len
405 * The length of the data to set.
406 *
407 * @returns
408 * 0 on success or -1 on failure. Will clear the finished/overflowed flags.
409 */
410 int
411 sbuf_bcpy(struct sbuf *s, const void *data, size_t len)
412 {
413 sbuf_clear(s);
414 return sbuf_bcat(s, data, len);
415 }
416
417 /*!
418 * @function sbuf_cat
419 *
420 * @brief
421 * Append a string to an sbuf, possibly expanding the backing buffer to
422 * accommodate.
423 *
424 * @param s
425 * The sbuf.
426 *
427 * @param str
428 * The string to append.
429 *
430 * @returns
431 * 0 on success, -1 on failure. Always fails if the sbuf is marked as
432 * overflowed.
433 */
434 int
435 sbuf_cat(struct sbuf *s, const char *str)
436 {
437 return sbuf_bcat(s, str, strlen(str));
438 }
439
440 /*!
441 * @function sbuf_cpy
442 *
443 * @brief
444 * Set the entire sbuf data to the given nul-terminated string, possibly
445 * expanding the backing buffer to accommodate it if necessary.
446 *
447 * @param s
448 * The sbuf.
449 *
450 * @param str
451 * The string to set the sbuf data to.
452 *
453 * @returns
454 * 0 on success, -1 on failure. Clears and resets the sbuf first.
455 */
456 int
457 sbuf_cpy(struct sbuf *s, const char *str)
458 {
459 sbuf_clear(s);
460 return sbuf_cat(s, str);
461 }
462
463 /*!
464 * @function sbuf_vprintf
465 *
466 * @brief
467 * Formatted-print into an sbuf using a va_list.
468 *
469 * @param s
470 * The sbuf.
471 *
472 * @param fmt
473 * The format string.
474 *
475 * @param ap
476 * The format string argument data.
477 *
478 * @returns
479 * 0 on success, -1 on failure. Always fails if the sbuf is marked as
480 * overflowed.
481 */
482 int
483 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
484 {
485 va_list ap_copy;
486 int result;
487 size_t capacity;
488 size_t len;
489
490 if (SBUF_HASOVERFLOWED(s)) {
491 return -1;
492 }
493
494 do {
495 capacity = sbuf_capacity(s);
496
497 va_copy(ap_copy, ap);
498 /* +1 for \0. safe because we already accommodate this. */
499 result = vsnprintf(&s->s_buf[s->s_len], capacity + 1, fmt, ap_copy);
500 va_end(ap_copy);
501
502 if (result < 0) {
503 return -1;
504 }
505
506 len = (size_t)result;
507 if (len <= capacity) {
508 s->s_len += (int)len;
509 return 0;
510 }
511 } while (-1 != sbuf_ensure_capacity(s, len));
512
513 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
514 return -1;
515 }
516
517 /*!
518 * @function sbuf_printf
519 *
520 * @brief
521 * Formatted-print into an sbuf using variadic arguments.
522 *
523 * @param s
524 * The sbuf.
525 *
526 * @param fmt
527 * The format string.
528 *
529 * @returns
530 * 0 on success, -1 on failure. Always fails if the sbuf is marked as
531 * overflowed.
532 */
533 int
534 sbuf_printf(struct sbuf *s, const char *fmt, ...)
535 {
536 va_list ap;
537 int result;
538
539 va_start(ap, fmt);
540 result = sbuf_vprintf(s, fmt, ap);
541 va_end(ap);
542 return result;
543 }
544
545 /*!
546 * @function sbuf_putc
547 *
548 * @brief
549 * Append a single character to an sbuf. Ignores '\0'.
550 *
551 * @param s
552 * The sbuf.
553 *
554 * @param c_
555 * The character to append.
556 *
557 * @returns
558 * 0 on success, -1 on failure. This function will always fail if the sbuf is
559 * marked as overflowed.
560 */
561 int
562 sbuf_putc(struct sbuf *s, int c_)
563 {
564 char c = (char)c_;
565
566 if (SBUF_HASOVERFLOWED(s)) {
567 return -1;
568 }
569
570 if (-1 == sbuf_ensure_capacity(s, 1)) {
571 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
572 return -1;
573 }
574
575 if (c != '\0') {
576 s->s_buf[s->s_len++] = c;
577 }
578
579 return 0;
580 }
581
582 static inline int
583 isspace(char ch)
584 {
585 return ch == ' ' || ch == '\n' || ch == '\t';
586 }
587
588 /*!
589 * @function sbuf_trim
590 *
591 * @brief
592 * Removes whitespace from the end of an sbuf.
593 *
594 * @param s
595 * The sbuf.
596 *
597 * @returns
598 * 0 on success or -1 if the sbuf is marked as overflowed.
599 */
600 int
601 sbuf_trim(struct sbuf *s)
602 {
603 if (SBUF_HASOVERFLOWED(s)) {
604 return -1;
605 }
606
607 while (s->s_len > 0 && isspace(s->s_buf[s->s_len - 1])) {
608 --s->s_len;
609 }
610
611 return 0;
612 }
613
614 /*!
615 * @function sbuf_overflowed
616 *
617 * @brief
618 * Indicates whether the sbuf is marked as overflowed.
619 *
620 * @param s
621 * The sbuf.
622 *
623 * @returns
624 * 1 if the sbuf has overflowed or 0 otherwise.
625 */
626 int
627 sbuf_overflowed(struct sbuf *s)
628 {
629 return !!SBUF_HASOVERFLOWED(s);
630 }
631
632 /*!
633 * @function sbuf_finish
634 *
635 * @brief
636 * Puts a trailing nul byte onto the sbuf data.
637 *
638 * @param s
639 * The sbuf.
640 */
641 void
642 sbuf_finish(struct sbuf *s)
643 {
644 /* safe because we always reserve a byte at the end for \0: */
645 s->s_buf[s->s_len] = '\0';
646 SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
647 SBUF_SETFLAG(s, SBUF_FINISHED);
648 }
649
650 /*!
651 * @function sbuf_data
652 *
653 * @brief
654 * Gets a pointer to the sbuf backing data.
655 *
656 * @param s
657 * The sbuf.
658 *
659 * @returns
660 * A pointer to the sbuf data.
661 */
662 char *
663 sbuf_data(struct sbuf *s)
664 {
665 return s->s_buf;
666 }
667
668 /*!
669 * @function sbuf_len
670 *
671 * @brief
672 * Retrieves the current length of the sbuf data.
673 *
674 * @param s
675 * The sbuf
676 *
677 * @returns
678 * The length of the sbuf data or -1 if the sbuf is marked as overflowed.
679 */
680 int
681 sbuf_len(struct sbuf *s)
682 {
683 if (SBUF_HASOVERFLOWED(s)) {
684 return -1;
685 }
686
687 return s->s_len;
688 }
689
690 /*!
691 * @function sbuf_done
692 *
693 * @brief
694 * Tests if the sbuf is marked as finished.
695 *
696 * @param s
697 * The sbuf.
698 *
699 * @returns
700 * 1 if the sbuf is marked as finished or 0 if not.
701 */
702 int
703 sbuf_done(struct sbuf *s)
704 {
705 return !!SBUF_ISFINISHED(s);
706 }
707
708 /*!
709 * @function sbuf_uionew
710 *
711 * @brief
712 * Create a new sbuf and initialize its buffer with data from the given uio.
713 *
714 * @param s
715 * An optional existing sbuf to initialize, or NULL to allocate a new one.
716 *
717 * @param uio
718 * The uio describing the data to populate the sbuf with.
719 *
720 * @param error
721 * An output parameter to report any error to.
722 *
723 * @returns
724 * The new and/or initialized sbuf, or NULL on error. The error code is
725 * reported back via @a error.
726 */
727 struct sbuf *
728 sbuf_uionew(struct sbuf *s, struct uio *uio, int *error)
729 {
730 int size;
731
732 if ((user_size_t)uio_resid(uio) > INT_MAX - 1) {
733 *error = EINVAL;
734 return NULL;
735 }
736
737 size = (int)uio_resid(uio);
738 s = sbuf_new(s, NULL, size + 1, 0);
739 if (s == NULL) {
740 *error = ENOMEM;
741 return NULL;
742 }
743
744 *error = uiomove(s->s_buf, size, uio);
745 if (*error != 0) {
746 sbuf_delete(s);
747 return NULL;
748 }
749
750 s->s_len = size;
751 *error = 0;
752
753 return s;
754 }
755
756 /*!
757 * @function sbuf_bcopyin
758 *
759 * @brief
760 * Append userland data to an sbuf.
761 *
762 * @param s
763 * The sbuf.
764 *
765 * @param uaddr
766 * The userland address of data to append to the sbuf.
767 *
768 * @param len
769 * The length of the data to copy from userland.
770 *
771 * @returns
772 * 0 on success or -1 on error. Always returns -1 if the sbuf is marked as
773 * overflowed.
774 */
775 int
776 sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
777 {
778 if (SBUF_HASOVERFLOWED(s)) {
779 return -1;
780 }
781
782 if (len == 0) {
783 return 0;
784 }
785
786 if (-1 == sbuf_ensure_capacity(s, len)) {
787 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
788 return -1;
789 }
790
791 if (copyin(CAST_USER_ADDR_T(uaddr), &s->s_buf[s->s_len], len) != 0) {
792 return -1;
793 }
794
795 s->s_len += (int)len;
796 return 0;
797 }
798
799 /*!
800 * @function sbuf_copyin
801 *
802 * @brief
803 * Append a userland string to an sbuf.
804 *
805 * @param s
806 * The sbuf.
807 *
808 * @param uaddr
809 * The userland address of the string to append to the sbuf.
810 *
811 * @param len
812 * The maximum length of the string to copy. If zero, the current capacity of
813 * the sbuf is used.
814 *
815 * @returns
816 * The number of bytes copied or -1 if an error occurred. Always returns -1 if
817 * the sbuf is marked as overflowed.
818 */
819 int
820 sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
821 {
822 size_t done;
823
824 if (SBUF_HASOVERFLOWED(s)) {
825 return -1;
826 }
827
828 if (len == 0) {
829 len = sbuf_capacity(s);
830 } else if (-1 == sbuf_ensure_capacity(s, len)) {
831 return -1;
832 }
833
834 switch (copyinstr(CAST_USER_ADDR_T(uaddr), &s->s_buf[s->s_len], len + 1, &done)) {
835 case ENAMETOOLONG:
836 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
837 s->s_len += done;
838 return -1;
839 case 0:
840 s->s_len += done - 1;
841 break;
842 default:
843 return -1;
844 }
845
846 return (int)done;
847 }
848
849 #if DEBUG || DEVELOPMENT
850
851 /*
852 * a = assertion string
853 */
854 #define SBUF_FAIL(a) \
855 MACRO_BEGIN \
856 printf("sbuf_tests: failed assertion: %s\n", a); \
857 if (what != NULL && should != NULL) { \
858 printf("sbuf_tests: while testing: %s should %s\n", what, should); \
859 } \
860 goto fail; \
861 MACRO_END
862
863 #define SBUF_PASS \
864 ++passed
865
866 /*
867 * x = expression
868 */
869 #define SBUF_ASSERT(x) \
870 MACRO_BEGIN \
871 if (x) { \
872 SBUF_PASS; \
873 } else { \
874 SBUF_FAIL(#x); \
875 } \
876 MACRO_END
877
878 #define SBUF_ASSERT_NOT(x) \
879 SBUF_ASSERT(!(x))
880
881 /*
882 * e = expected
883 * a = actual
884 * c = comparator
885 */
886 #define SBUF_ASSERT_CMP(e, a, c) \
887 MACRO_BEGIN \
888 if ((a) c (e)) { \
889 SBUF_PASS; \
890 } else { \
891 SBUF_FAIL(#a " " #c " " #e); \
892 } \
893 MACRO_END
894
895 #define SBUF_ASSERT_EQ(e, a) SBUF_ASSERT_CMP(e, a, ==)
896 #define SBUF_ASSERT_NE(e, a) SBUF_ASSERT_CMP(e, a, !=)
897 #define SBUF_ASSERT_GT(e, a) SBUF_ASSERT_CMP(e, a, >)
898 #define SBUF_ASSERT_GTE(e, a) SBUF_ASSERT_CMP(e, a, >=)
899 #define SBUF_ASSERT_LT(e, a) SBUF_ASSERT_CMP(e, a, <)
900 #define SBUF_ASSERT_LTE(e, a) SBUF_ASSERT_CMP(e, a, <=)
901
902 #define SBUF_TEST_BEGIN \
903 size_t passed = 0; \
904 const char *what = NULL; \
905 const char *should = NULL;
906
907 /*
908 * include the trailing semi-colons here intentionally to allow for block-like
909 * appearance:
910 */
911 #define SBUF_TESTING(f) \
912 MACRO_BEGIN \
913 what = (f); \
914 MACRO_END;
915
916 #define SBUF_SHOULD(s) \
917 MACRO_BEGIN \
918 should = (s); \
919 MACRO_END;
920
921 #define SBUF_TEST_END \
922 printf("sbuf_tests: %zu assertions passed\n", passed); \
923 return 0; \
924 fail: \
925 return ENOTRECOVERABLE;
926
927 static int
928 sysctl_sbuf_tests SYSCTL_HANDLER_ARGS
929 {
930 #pragma unused(arg1, arg2)
931 int rval = 0;
932 char str[32] = { 'o', 'k', 0 };
933
934 rval = sysctl_handle_string(oidp, str, sizeof(str), req);
935 if (rval != 0 || req->newptr == 0 || req->newlen < 1) {
936 return rval;
937 }
938
939 SBUF_TEST_BEGIN;
940
941 SBUF_TESTING("sbuf_new")
942 {
943 SBUF_SHOULD("fail to allocate >INT_MAX")
944 {
945 struct sbuf *s = NULL;
946
947 s = sbuf_new(NULL, NULL, INT_MAX + 1, 0);
948 SBUF_ASSERT_EQ(NULL, s);
949 }
950
951 SBUF_SHOULD("fail when claiming a backing buffer >INT_MAX")
952 {
953 struct sbuf *s = NULL;
954 char buf[4] = { 0 };
955
956 s = sbuf_new(NULL, buf, INT_MAX + 1, 0);
957 SBUF_ASSERT_EQ(NULL, s);
958 }
959
960 SBUF_SHOULD("fail to allocate a zero-length sbuf")
961 {
962 struct sbuf *s = NULL;
963
964 s = sbuf_new(NULL, NULL, 0, 0);
965 SBUF_ASSERT_EQ(NULL, s);
966 }
967
968 SBUF_SHOULD("not accept invalid flags")
969 {
970 struct sbuf *s = NULL;
971
972 s = sbuf_new(NULL, NULL, 16, 0x10000);
973 SBUF_ASSERT_EQ(NULL, s);
974 }
975
976 SBUF_SHOULD("succeed when passed an existing sbuf")
977 {
978 struct sbuf *s = NULL;
979 struct sbuf existing;
980
981 memset(&existing, 0x41, sizeof(existing));
982 s = sbuf_new(&existing, NULL, 16, SBUF_AUTOEXTEND);
983 SBUF_ASSERT_EQ(&existing, s);
984 SBUF_ASSERT(SBUF_ISSET(s, SBUF_AUTOEXTEND));
985 SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNAMIC));
986 SBUF_ASSERT_NE(NULL, s->s_buf);
987 SBUF_ASSERT_NE(0, s->s_size);
988 SBUF_ASSERT_EQ(0, s->s_len);
989
990 sbuf_delete(s);
991 }
992
993 SBUF_SHOULD("succeed when passed an existing sbuf and buffer")
994 {
995 struct sbuf *s = NULL;
996 struct sbuf existing;
997 char buf[4] = { 0 };
998
999 memset(&existing, 0x41, sizeof(existing));
1000 s = sbuf_new(&existing, buf, sizeof(buf), 0);
1001 SBUF_ASSERT_EQ(&existing, s);
1002 SBUF_ASSERT_EQ(buf, s->s_buf);
1003 SBUF_ASSERT_EQ(4, s->s_size);
1004 SBUF_ASSERT_EQ(0, s->s_len);
1005
1006 sbuf_delete(s);
1007 }
1008
1009 SBUF_SHOULD("succeed without an existing sbuf or buffer")
1010 {
1011 struct sbuf *s = NULL;
1012
1013 s = sbuf_new(NULL, NULL, 16, 0);
1014 SBUF_ASSERT_NE(NULL, s);
1015 SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNAMIC));
1016 SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNSTRUCT));
1017 SBUF_ASSERT_NE(NULL, s->s_buf);
1018 SBUF_ASSERT_NE(0, s->s_size);
1019 SBUF_ASSERT_EQ(0, s->s_len);
1020
1021 sbuf_delete(s);
1022 }
1023
1024 SBUF_SHOULD("succeed without an existing sbuf, but with a buffer")
1025 {
1026 struct sbuf *s = NULL;
1027 char buf[4] = { 0 };
1028
1029 s = sbuf_new(NULL, buf, sizeof(buf), 0);
1030 SBUF_ASSERT_NE(NULL, s);
1031 SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNSTRUCT));
1032 SBUF_ASSERT_EQ(buf, s->s_buf);
1033 SBUF_ASSERT_EQ(4, s->s_size);
1034 SBUF_ASSERT_EQ(0, s->s_len);
1035
1036 sbuf_delete(s);
1037 }
1038
1039 SBUF_SHOULD("round up the requested size if SBUF_AUTOEXTEND")
1040 {
1041 struct sbuf *s = NULL;
1042
1043 s = sbuf_new(NULL, NULL, 1, SBUF_AUTOEXTEND);
1044 SBUF_ASSERT_GT(1, s->s_size);
1045
1046 sbuf_delete(s);
1047 }
1048 }
1049
1050 SBUF_TESTING("sbuf_clear")
1051 {
1052 SBUF_SHOULD("clear the overflowed and finished flags")
1053 {
1054 struct sbuf *s = NULL;
1055
1056 s = sbuf_new(NULL, NULL, 16, 0);
1057
1058 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1059 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1060 SBUF_SETFLAG(s, SBUF_FINISHED);
1061 SBUF_ASSERT(SBUF_ISSET(s, SBUF_FINISHED));
1062 sbuf_clear(s);
1063 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1064 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_FINISHED));
1065
1066 sbuf_delete(s);
1067 }
1068
1069 SBUF_SHOULD("reset the position to zero")
1070 {
1071 struct sbuf *s = NULL;
1072
1073 s = sbuf_new(NULL, NULL, 16, 0);
1074
1075 s->s_len = 1;
1076 sbuf_clear(s);
1077 SBUF_ASSERT_EQ(0, s->s_len);
1078
1079 sbuf_delete(s);
1080 }
1081 }
1082
1083 SBUF_TESTING("sbuf_extend")
1084 {
1085 SBUF_SHOULD("allow zero")
1086 {
1087 struct sbuf *s = NULL;
1088 int size_before;
1089
1090 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1091 size_before = s->s_size;
1092 SBUF_ASSERT_EQ(0, sbuf_extend(s, 0));
1093 SBUF_ASSERT_EQ(size_before, s->s_size);
1094
1095 sbuf_delete(s);
1096 }
1097
1098 SBUF_SHOULD("fail for sbuf not marked as SBUF_AUTOEXTEND")
1099 {
1100 struct sbuf *s = NULL;
1101
1102 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1103 SBUF_ASSERT_EQ(-1, sbuf_extend(s, 10));
1104
1105 sbuf_delete(s);
1106 }
1107
1108 SBUF_SHOULD("accommodate reasonable requests")
1109 {
1110 struct sbuf *s = NULL;
1111 int size_before;
1112
1113 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1114 size_before = s->s_size;
1115
1116 SBUF_ASSERT_EQ(0, sbuf_extend(s, 10));
1117 SBUF_ASSERT_GTE(10, s->s_size - size_before);
1118
1119 sbuf_delete(s);
1120 }
1121
1122 SBUF_SHOULD("reject requests that cause overflows")
1123 {
1124 struct sbuf *s = NULL;
1125
1126 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1127 SBUF_ASSERT_EQ(-1, sbuf_extend(s, SIZE_MAX));
1128 SBUF_ASSERT_EQ(-1, sbuf_extend(s, INT_MAX));
1129
1130 sbuf_delete(s);
1131 }
1132
1133 SBUF_SHOULD("transform the sbuf into an SBUF_DYNAMIC one")
1134 {
1135 struct sbuf *s = NULL;
1136 char buf[4] = { 0 };
1137
1138 s = sbuf_new(NULL, buf, sizeof(buf), SBUF_AUTOEXTEND);
1139 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_DYNAMIC));
1140 SBUF_ASSERT_EQ(0, sbuf_extend(s, 10));
1141 SBUF_ASSERT(SBUF_ISSET(s, SBUF_DYNAMIC));
1142
1143 sbuf_delete(s);
1144 }
1145 }
1146
1147 SBUF_TESTING("sbuf_capacity")
1148 {
1149 SBUF_SHOULD("account for the trailing nul byte")
1150 {
1151 struct sbuf *s = NULL;
1152
1153 s = sbuf_new(NULL, NULL, 16, 0);
1154 SBUF_ASSERT_EQ(s->s_size - s->s_len - 1, sbuf_capacity(s));
1155
1156 sbuf_delete(s);
1157 }
1158 }
1159
1160 SBUF_TESTING("sbuf_ensure_capacity")
1161 {
1162 SBUF_SHOULD("return 0 if the sbuf already has enough capacity")
1163 {
1164 struct sbuf *s = NULL;
1165 int size_before;
1166
1167 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1168 size_before = s->s_size;
1169 SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s, 5));
1170 SBUF_ASSERT_EQ(size_before, s->s_size);
1171
1172 sbuf_delete(s);
1173 }
1174
1175 SBUF_SHOULD("extend the buffer as needed")
1176 {
1177 struct sbuf *s = NULL;
1178 int size_before;
1179
1180 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1181 size_before = s->s_size;
1182 SBUF_ASSERT_EQ(0, sbuf_ensure_capacity(s, 30));
1183 SBUF_ASSERT_GT(size_before, s->s_size);
1184
1185 sbuf_delete(s);
1186 }
1187 }
1188
1189 SBUF_TESTING("sbuf_bcat")
1190 {
1191 SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1192 {
1193 struct sbuf *s = NULL;
1194
1195 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1196 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1197 SBUF_ASSERT_EQ(-1, sbuf_bcat(s, "A", 1));
1198
1199 sbuf_delete(s);
1200 }
1201
1202 SBUF_SHOULD("fail if len is too big")
1203 {
1204 struct sbuf *s = NULL;
1205
1206 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1207 SBUF_ASSERT_EQ(-1, sbuf_bcat(s, "A", INT_MAX));
1208 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1209
1210 sbuf_delete(s);
1211 }
1212
1213 SBUF_SHOULD("succeed for a fixed buf within limits")
1214 {
1215 struct sbuf *s = NULL;
1216
1217 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1218 SBUF_ASSERT_EQ(0, sbuf_bcat(s, "ABC", 3));
1219 SBUF_ASSERT_EQ(3, s->s_len);
1220 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1221 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1222 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1223
1224 sbuf_delete(s);
1225 }
1226
1227 SBUF_SHOULD("succeed for binary data, even with nul bytes")
1228 {
1229 struct sbuf *s = NULL;
1230
1231 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1232 SBUF_ASSERT_EQ(0, sbuf_bcat(s, "A\0C", 3));
1233 SBUF_ASSERT_EQ(3, s->s_len);
1234 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1235 SBUF_ASSERT_EQ('\0', s->s_buf[1]);
1236 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1237
1238 sbuf_delete(s);
1239 }
1240
1241 SBUF_SHOULD("append to existing data")
1242 {
1243 struct sbuf *s = NULL;
1244
1245 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1246 SBUF_ASSERT_EQ(0, sbuf_bcat(s, "ABC", 3));
1247 SBUF_ASSERT_EQ(3, s->s_len);
1248 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1249 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1250 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1251
1252 SBUF_ASSERT_EQ(0, sbuf_bcat(s, "DEF", 3));
1253 SBUF_ASSERT_EQ(6, s->s_len);
1254 SBUF_ASSERT_EQ('D', s->s_buf[3]);
1255 SBUF_ASSERT_EQ('E', s->s_buf[4]);
1256 SBUF_ASSERT_EQ('F', s->s_buf[5]);
1257
1258 sbuf_delete(s);
1259 }
1260
1261 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1262 {
1263 struct sbuf *s = NULL;
1264
1265 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1266 SBUF_ASSERT_EQ(0, sbuf_bcat(s, "0123456789abcde", 15));
1267 SBUF_ASSERT_EQ(15, s->s_len);
1268
1269 sbuf_delete(s);
1270 }
1271
1272 SBUF_SHOULD("fail for a fixed buf if too big")
1273 {
1274 struct sbuf *s = NULL;
1275
1276 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1277 SBUF_ASSERT_EQ(-1, sbuf_bcat(s, "0123456789abcdef", 16));
1278 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1279
1280 sbuf_delete(s);
1281 }
1282
1283 SBUF_SHOULD("expand the backing buffer as needed")
1284 {
1285 struct sbuf *s = NULL;
1286 int size_before;
1287
1288 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1289 size_before = s->s_size;
1290 SBUF_ASSERT_EQ(0, sbuf_bcat(s, "0123456789abcdef", 16));
1291 SBUF_ASSERT_GT(size_before, s->s_size);
1292 SBUF_ASSERT_EQ(16, s->s_len);
1293
1294 sbuf_delete(s);
1295 }
1296 }
1297
1298 SBUF_TESTING("sbuf_bcpy")
1299 {
1300 SBUF_SHOULD("overwrite any existing data")
1301 {
1302 struct sbuf *s = NULL;
1303
1304 s = sbuf_new(NULL, NULL, 16, 0);
1305 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "ABC", 3));
1306 SBUF_ASSERT_EQ(3, s->s_len);
1307 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1308 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1309 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1310
1311 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "XYZ123", 6));
1312 SBUF_ASSERT_EQ(6, s->s_len);
1313 SBUF_ASSERT_EQ('X', s->s_buf[0]);
1314 SBUF_ASSERT_EQ('Y', s->s_buf[1]);
1315 SBUF_ASSERT_EQ('Z', s->s_buf[2]);
1316 SBUF_ASSERT_EQ('1', s->s_buf[3]);
1317 SBUF_ASSERT_EQ('2', s->s_buf[4]);
1318 SBUF_ASSERT_EQ('3', s->s_buf[5]);
1319
1320 sbuf_delete(s);
1321 }
1322
1323 SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space")
1324 {
1325 struct sbuf *s = NULL;
1326
1327 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1328 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1329 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "A", 1));
1330
1331 sbuf_delete(s);
1332 }
1333
1334 SBUF_SHOULD("fail if len is too big")
1335 {
1336 struct sbuf *s = NULL;
1337
1338 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1339 SBUF_ASSERT_EQ(-1, sbuf_bcpy(s, "A", INT_MAX));
1340 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1341
1342 sbuf_delete(s);
1343 }
1344
1345 SBUF_SHOULD("succeed for a fixed buf within limits")
1346 {
1347 struct sbuf *s = NULL;
1348
1349 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1350 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "ABC", 3));
1351 SBUF_ASSERT_EQ(3, s->s_len);
1352 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1353 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1354 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1355
1356 sbuf_delete(s);
1357 }
1358
1359 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1360 {
1361 struct sbuf *s = NULL;
1362
1363 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1364 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "0123456789abcde", 15));
1365 SBUF_ASSERT_EQ(15, s->s_len);
1366
1367 sbuf_delete(s);
1368 }
1369
1370 SBUF_SHOULD("fail for a fixed buf if too big")
1371 {
1372 struct sbuf *s = NULL;
1373
1374 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1375 SBUF_ASSERT_EQ(-1, sbuf_bcpy(s, "0123456789abcdef", 16));
1376 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1377
1378 sbuf_delete(s);
1379 }
1380
1381 SBUF_SHOULD("expand the backing buffer as needed")
1382 {
1383 struct sbuf *s = NULL;
1384 int size_before;
1385
1386 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1387 size_before = s->s_size;
1388 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "0123456789abcdef", 16));
1389 SBUF_ASSERT_GT(size_before, s->s_size);
1390 SBUF_ASSERT_EQ(16, s->s_len);
1391
1392 sbuf_delete(s);
1393 }
1394 }
1395
1396 SBUF_TESTING("sbuf_cat")
1397 {
1398 SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1399 {
1400 struct sbuf *s = NULL;
1401
1402 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1403 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1404 SBUF_ASSERT_EQ(-1, sbuf_cat(s, "A"));
1405
1406 sbuf_delete(s);
1407 }
1408
1409 SBUF_SHOULD("succeed for a fixed buf within limits")
1410 {
1411 struct sbuf *s = NULL;
1412
1413 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1414 SBUF_ASSERT_EQ(0, sbuf_cat(s, "ABC"));
1415 SBUF_ASSERT_EQ(3, s->s_len);
1416 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1417 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1418 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1419
1420 sbuf_delete(s);
1421 }
1422
1423 SBUF_SHOULD("only copy up to a nul byte")
1424 {
1425 struct sbuf *s = NULL;
1426
1427 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1428 SBUF_ASSERT_EQ(0, sbuf_cat(s, "A\0C"));
1429 SBUF_ASSERT_EQ(1, s->s_len);
1430 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1431
1432 sbuf_delete(s);
1433 }
1434
1435 SBUF_SHOULD("append to existing data")
1436 {
1437 struct sbuf *s = NULL;
1438
1439 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1440 SBUF_ASSERT_EQ(0, sbuf_cat(s, "ABC"));
1441 SBUF_ASSERT_EQ(3, s->s_len);
1442 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1443 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1444 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1445
1446 SBUF_ASSERT_EQ(0, sbuf_cat(s, "DEF"));
1447 SBUF_ASSERT_EQ(6, s->s_len);
1448 SBUF_ASSERT_EQ('D', s->s_buf[3]);
1449 SBUF_ASSERT_EQ('E', s->s_buf[4]);
1450 SBUF_ASSERT_EQ('F', s->s_buf[5]);
1451
1452 sbuf_delete(s);
1453 }
1454
1455 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1456 {
1457 struct sbuf *s = NULL;
1458
1459 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1460 SBUF_ASSERT_EQ(0, sbuf_cat(s, "0123456789abcde"));
1461 SBUF_ASSERT_EQ(15, s->s_len);
1462
1463 sbuf_delete(s);
1464 }
1465
1466 SBUF_SHOULD("fail for a fixed buf if too big")
1467 {
1468 struct sbuf *s = NULL;
1469
1470 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1471 SBUF_ASSERT_EQ(-1, sbuf_cat(s, "0123456789abcdef"));
1472 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1473
1474 sbuf_delete(s);
1475 }
1476
1477 SBUF_SHOULD("expand the backing buffer as needed")
1478 {
1479 struct sbuf *s = NULL;
1480 int size_before;
1481
1482 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1483 size_before = s->s_size;
1484 SBUF_ASSERT_EQ(0, sbuf_cat(s, "0123456789abcdef"));
1485 SBUF_ASSERT_GT(size_before, s->s_size);
1486 SBUF_ASSERT_EQ(16, s->s_len);
1487
1488 sbuf_delete(s);
1489 }
1490 }
1491
1492 SBUF_TESTING("sbuf_cpy")
1493 {
1494 SBUF_SHOULD("overwrite any existing data")
1495 {
1496 struct sbuf *s = NULL;
1497
1498 s = sbuf_new(NULL, NULL, 16, 0);
1499 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "ABC"));
1500 SBUF_ASSERT_EQ(3, s->s_len);
1501 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1502 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1503 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1504
1505 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "XYZ123"));
1506 SBUF_ASSERT_EQ(6, s->s_len);
1507 SBUF_ASSERT_EQ('X', s->s_buf[0]);
1508 SBUF_ASSERT_EQ('Y', s->s_buf[1]);
1509 SBUF_ASSERT_EQ('Z', s->s_buf[2]);
1510 SBUF_ASSERT_EQ('1', s->s_buf[3]);
1511 SBUF_ASSERT_EQ('2', s->s_buf[4]);
1512 SBUF_ASSERT_EQ('3', s->s_buf[5]);
1513
1514 sbuf_delete(s);
1515 }
1516
1517 SBUF_SHOULD("succeed if the sbuf is marked as overflowed, but there is space")
1518 {
1519 struct sbuf *s = NULL;
1520
1521 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1522 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1523 SBUF_ASSERT_EQ(0, sbuf_bcpy(s, "A", 1));
1524
1525 sbuf_delete(s);
1526 }
1527
1528 SBUF_SHOULD("succeed for a fixed buf within limits")
1529 {
1530 struct sbuf *s = NULL;
1531
1532 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1533 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "ABC"));
1534 SBUF_ASSERT_EQ(3, s->s_len);
1535 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1536 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1537 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1538
1539 sbuf_delete(s);
1540 }
1541
1542 SBUF_SHOULD("succeed for a fixed buf right up to the limit")
1543 {
1544 struct sbuf *s = NULL;
1545
1546 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1547 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
1548 SBUF_ASSERT_EQ(15, s->s_len);
1549
1550 sbuf_delete(s);
1551 }
1552
1553 SBUF_SHOULD("fail for a fixed buf if too big")
1554 {
1555 struct sbuf *s = NULL;
1556
1557 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1558 SBUF_ASSERT_EQ(-1, sbuf_cpy(s, "0123456789abcdef"));
1559 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1560
1561 sbuf_delete(s);
1562 }
1563
1564 SBUF_SHOULD("expand the backing buffer as needed")
1565 {
1566 struct sbuf *s = NULL;
1567 int size_before;
1568
1569 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1570 size_before = s->s_size;
1571 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcdef"));
1572 SBUF_ASSERT_GT(size_before, s->s_size);
1573 SBUF_ASSERT_EQ(16, s->s_len);
1574
1575 sbuf_delete(s);
1576 }
1577 }
1578
1579 /* also tests sbuf_vprintf: */
1580 SBUF_TESTING("sbuf_printf")
1581 {
1582 SBUF_SHOULD("support simple printing")
1583 {
1584 struct sbuf *s = NULL;
1585
1586 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1587 SBUF_ASSERT_EQ(0, sbuf_printf(s, "hello"));
1588 SBUF_ASSERT_EQ(5, s->s_len);
1589 SBUF_ASSERT_EQ('h', s->s_buf[0]);
1590 SBUF_ASSERT_EQ('e', s->s_buf[1]);
1591 SBUF_ASSERT_EQ('l', s->s_buf[2]);
1592 SBUF_ASSERT_EQ('l', s->s_buf[3]);
1593 SBUF_ASSERT_EQ('o', s->s_buf[4]);
1594
1595 sbuf_delete(s);
1596 }
1597
1598 SBUF_SHOULD("support format strings")
1599 {
1600 struct sbuf *s = NULL;
1601 char data1 = 'A';
1602 int data2 = 123;
1603 const char *data3 = "foo";
1604
1605 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1606 SBUF_ASSERT_EQ(0, sbuf_printf(s, "%c %d %s", data1, data2, data3));
1607 SBUF_ASSERT_EQ(9, s->s_len);
1608 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1609 SBUF_ASSERT_EQ(' ', s->s_buf[1]);
1610 SBUF_ASSERT_EQ('1', s->s_buf[2]);
1611 SBUF_ASSERT_EQ('2', s->s_buf[3]);
1612 SBUF_ASSERT_EQ('3', s->s_buf[4]);
1613 SBUF_ASSERT_EQ(' ', s->s_buf[5]);
1614 SBUF_ASSERT_EQ('f', s->s_buf[6]);
1615 SBUF_ASSERT_EQ('o', s->s_buf[7]);
1616 SBUF_ASSERT_EQ('o', s->s_buf[8]);
1617
1618 sbuf_delete(s);
1619 }
1620
1621 SBUF_SHOULD("work with the fact we reserve a nul byte at the end")
1622 {
1623 struct sbuf *s = NULL;
1624
1625 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1626 SBUF_ASSERT_EQ(0, sbuf_printf(s, "0123456789abcde"));
1627 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1628
1629 sbuf_delete(s);
1630 }
1631
1632 SBUF_SHOULD("mark the sbuf as overflowed if we try to write too much")
1633 {
1634 struct sbuf *s = NULL;
1635
1636 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1637 SBUF_ASSERT_EQ(-1, sbuf_printf(s, "0123456789abcdef"));
1638 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1639
1640 sbuf_delete(s);
1641 }
1642
1643 SBUF_SHOULD("auto-extend as necessary")
1644 {
1645 struct sbuf *s = NULL;
1646 const char *data = "0123456789abcdef";
1647 int size_before;
1648 size_t n;
1649
1650 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1651 size_before = s->s_size;
1652 SBUF_ASSERT_EQ(0, sbuf_printf(s, "%s", data));
1653 SBUF_ASSERT_GT(size_before, s->s_size);
1654
1655 for (n = 0; n < strlen(data); ++n) {
1656 SBUF_ASSERT_EQ(data[n], s->s_buf[n]);
1657 }
1658
1659 sbuf_delete(s);
1660 }
1661
1662 SBUF_SHOULD("fail if the sbuf is marked as overflowed")
1663 {
1664 struct sbuf *s = NULL;
1665
1666 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1667 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1668 SBUF_ASSERT_EQ(-1, sbuf_printf(s, "A"));
1669
1670 sbuf_delete(s);
1671 }
1672 }
1673
1674 SBUF_TESTING("sbuf_putc")
1675 {
1676 SBUF_SHOULD("work where we have capacity")
1677 {
1678 struct sbuf *s = NULL;
1679
1680 s = sbuf_new(NULL, NULL, 16, 0);
1681 SBUF_ASSERT_EQ(0, sbuf_putc(s, 'a'));
1682 SBUF_ASSERT_EQ(1, s->s_len);
1683 SBUF_ASSERT_EQ('a', s->s_buf[0]);
1684
1685 sbuf_delete(s);
1686 }
1687
1688 SBUF_SHOULD("fail if we have a full, fixedlen sbuf")
1689 {
1690 struct sbuf *s = NULL;
1691
1692 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
1693 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcd"));
1694 SBUF_ASSERT_EQ(0, sbuf_putc(s, 'e'));
1695 SBUF_ASSERT_EQ(-1, sbuf_putc(s, 'f'));
1696 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1697
1698 sbuf_delete(s);
1699 }
1700
1701 SBUF_SHOULD("ignore nul")
1702 {
1703 struct sbuf *s = NULL;
1704
1705 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1706 SBUF_ASSERT_EQ(0, sbuf_putc(s, '\0'));
1707 SBUF_ASSERT_EQ(0, s->s_len);
1708
1709 sbuf_delete(s);
1710 }
1711
1712 SBUF_SHOULD("auto-extend if necessary")
1713 {
1714 struct sbuf *s = NULL;
1715 int len_before;
1716 int size_before;
1717
1718 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1719 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
1720 len_before = s->s_len;
1721 size_before = s->s_size;
1722 SBUF_ASSERT_EQ(0, sbuf_putc(s, 'f'));
1723 SBUF_ASSERT_EQ(len_before + 1, s->s_len);
1724 SBUF_ASSERT_GT(size_before, s->s_size);
1725 SBUF_ASSERT_EQ('f', s->s_buf[s->s_len - 1]);
1726
1727 sbuf_delete(s);
1728 }
1729
1730 SBUF_SHOULD("fail if the sbuf is overflowed")
1731 {
1732 struct sbuf *s = NULL;
1733
1734 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
1735 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1736 SBUF_ASSERT_EQ(-1, sbuf_putc(s, 'a'));
1737
1738 sbuf_delete(s);
1739 }
1740 }
1741
1742 SBUF_TESTING("sbuf_trim")
1743 {
1744 SBUF_SHOULD("remove trailing spaces, tabs and newlines")
1745 {
1746 struct sbuf *s = NULL;
1747 const char *test = "foo \t\t\n\t";
1748
1749 s = sbuf_new(NULL, NULL, 16, 0);
1750 SBUF_ASSERT_EQ(0, sbuf_cpy(s, test));
1751 SBUF_ASSERT_EQ(strlen(test), s->s_len);
1752 SBUF_ASSERT_EQ(0, sbuf_trim(s));
1753 SBUF_ASSERT_EQ(3, s->s_len);
1754
1755 sbuf_delete(s);
1756 }
1757
1758 SBUF_SHOULD("do nothing if there is no trailing whitespace")
1759 {
1760 struct sbuf *s = NULL;
1761 const char *test = "foo";
1762
1763 s = sbuf_new(NULL, NULL, 16, 0);
1764 SBUF_ASSERT_EQ(0, sbuf_cpy(s, test));
1765 SBUF_ASSERT_EQ(strlen(test), s->s_len);
1766 SBUF_ASSERT_EQ(0, sbuf_trim(s));
1767 SBUF_ASSERT_EQ(strlen(test), s->s_len);
1768
1769 sbuf_delete(s);
1770 }
1771
1772 SBUF_SHOULD("fail if the sbuf is overflowed")
1773 {
1774 struct sbuf *s = NULL;
1775 const char *test = "foo ";
1776
1777 s = sbuf_new(NULL, NULL, 16, 0);
1778 SBUF_ASSERT_EQ(0, sbuf_cpy(s, test));
1779 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1780 SBUF_ASSERT_EQ(-1, sbuf_trim(s));
1781 SBUF_ASSERT_EQ(strlen(test), s->s_len);
1782
1783 sbuf_delete(s);
1784 }
1785
1786 SBUF_SHOULD("work on empty strings")
1787 {
1788 struct sbuf *s = NULL;
1789
1790 s = sbuf_new(NULL, NULL, 16, 0);
1791 SBUF_ASSERT_EQ(0, sbuf_trim(s));
1792 SBUF_ASSERT_EQ(0, s->s_len);
1793
1794 sbuf_delete(s);
1795 }
1796 }
1797
1798 SBUF_TESTING("sbuf_overflowed")
1799 {
1800 SBUF_SHOULD("return false if it hasn't overflowed")
1801 {
1802 struct sbuf *s = NULL;
1803
1804 s = sbuf_new(NULL, NULL, 16, 0);
1805 SBUF_ASSERT_NOT(sbuf_overflowed(s));
1806
1807 sbuf_delete(s);
1808 }
1809
1810 SBUF_SHOULD("return true if it has overflowed")
1811 {
1812 struct sbuf *s = NULL;
1813
1814 s = sbuf_new(NULL, NULL, 16, 0);
1815 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1816 SBUF_ASSERT(sbuf_overflowed(s));
1817
1818 sbuf_delete(s);
1819 }
1820 }
1821
1822 SBUF_TESTING("sbuf_finish")
1823 {
1824 SBUF_SHOULD("insert a nul byte, clear the overflowed flag and set the finished flag")
1825 {
1826 struct sbuf *s = NULL;
1827
1828 s = sbuf_new(NULL, NULL, 16, 0);
1829 SBUF_ASSERT_EQ(0, sbuf_putc(s, 'A'));
1830 s->s_buf[s->s_len] = 'x';
1831 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1832 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_FINISHED));
1833
1834 sbuf_finish(s);
1835
1836 SBUF_ASSERT_EQ(0, s->s_buf[s->s_len]);
1837 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
1838 SBUF_ASSERT(SBUF_ISSET(s, SBUF_FINISHED));
1839
1840 sbuf_delete(s);
1841 }
1842 }
1843
1844 SBUF_TESTING("sbuf_data")
1845 {
1846 SBUF_SHOULD("return the s_buf pointer")
1847 {
1848 struct sbuf *s = NULL;
1849
1850 s = sbuf_new(NULL, NULL, 16, 0);
1851 SBUF_ASSERT_EQ(s->s_buf, sbuf_data(s));
1852
1853 sbuf_delete(s);
1854 }
1855
1856 SBUF_SHOULD("return the buffer we gave it")
1857 {
1858 struct sbuf *s = NULL;
1859 char buf[4] = { 0 };
1860
1861 s = sbuf_new(NULL, buf, sizeof(buf), 0);
1862 SBUF_ASSERT_EQ(buf, sbuf_data(s));
1863
1864 sbuf_delete(s);
1865 }
1866 }
1867
1868 SBUF_TESTING("sbuf_len")
1869 {
1870 SBUF_SHOULD("return the length of the sbuf data")
1871 {
1872 struct sbuf *s = NULL;
1873
1874 s = sbuf_new(NULL, NULL, 16, 0);
1875 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "hello"));
1876 SBUF_ASSERT_EQ(5, sbuf_len(s));
1877
1878 sbuf_delete(s);
1879 }
1880
1881 SBUF_SHOULD("return -1 if the sbuf is overflowed")
1882 {
1883 struct sbuf *s = NULL;
1884
1885 s = sbuf_new(NULL, NULL, 16, 0);
1886 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "hello"));
1887 SBUF_ASSERT_EQ(5, sbuf_len(s));
1888 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
1889 SBUF_ASSERT_EQ(-1, sbuf_len(s));
1890
1891 sbuf_delete(s);
1892 }
1893 }
1894
1895 SBUF_TESTING("sbuf_done")
1896 {
1897 SBUF_SHOULD("return false if the sbuf isn't finished")
1898 {
1899 struct sbuf *s = NULL;
1900
1901 s = sbuf_new(NULL, NULL, 16, 0);
1902 SBUF_ASSERT_NOT(sbuf_done(s));
1903
1904 sbuf_delete(s);
1905 }
1906
1907 SBUF_SHOULD("return true if the sbuf has finished")
1908 {
1909 struct sbuf *s = NULL;
1910
1911 s = sbuf_new(NULL, NULL, 16, 0);
1912 SBUF_ASSERT_NOT(sbuf_done(s));
1913 SBUF_SETFLAG(s, SBUF_FINISHED);
1914 SBUF_ASSERT(sbuf_done(s));
1915
1916 sbuf_delete(s);
1917 }
1918 }
1919
1920 SBUF_TESTING("sbuf_delete")
1921 {
1922 SBUF_SHOULD("just free the backing buffer if we supplied an sbuf")
1923 {
1924 struct sbuf *s = NULL;
1925 struct sbuf existing = {};
1926
1927 s = sbuf_new(&existing, NULL, 16, 0);
1928 SBUF_ASSERT_NE(NULL, s->s_buf);
1929
1930 sbuf_delete(s);
1931 SBUF_ASSERT_EQ(NULL, s->s_buf);
1932 }
1933 }
1934
1935 SBUF_TESTING("sbuf_uionew")
1936 {
1937 SBUF_SHOULD("reject residuals that are too large")
1938 {
1939 struct sbuf *s = NULL;
1940 uio_t auio = NULL;
1941 char buf[4];
1942 int error = 0;
1943
1944 buf[0] = 'A';
1945 buf[1] = 'B';
1946 buf[2] = 'C';
1947 buf[3] = 'D';
1948
1949 auio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ);
1950 uio_addiov(auio, (user_addr_t)buf, INT_MAX);
1951
1952 s = sbuf_uionew(NULL, auio, &error);
1953 SBUF_ASSERT_EQ(NULL, s);
1954 SBUF_ASSERT_EQ(EINVAL, error);
1955
1956 uio_free(auio);
1957 }
1958
1959 SBUF_SHOULD("initialize using data described by the uio")
1960 {
1961 struct sbuf *s = NULL;
1962 uio_t auio = NULL;
1963 char buf[4];
1964 int error = 0;
1965
1966 buf[0] = 'A';
1967 buf[1] = 'B';
1968 buf[2] = 'C';
1969 buf[3] = 'D';
1970
1971 auio = uio_create(1, 0, UIO_SYSSPACE, UIO_WRITE);
1972 uio_addiov(auio, (user_addr_t)buf, sizeof(buf));
1973
1974 s = sbuf_uionew(NULL, auio, &error);
1975 SBUF_ASSERT_NE(NULL, s);
1976 SBUF_ASSERT_EQ(0, error);
1977 SBUF_ASSERT_EQ(4, s->s_len);
1978 SBUF_ASSERT_EQ('A', s->s_buf[0]);
1979 SBUF_ASSERT_EQ('B', s->s_buf[1]);
1980 SBUF_ASSERT_EQ('C', s->s_buf[2]);
1981 SBUF_ASSERT_EQ('D', s->s_buf[3]);
1982
1983 sbuf_delete(s);
1984 uio_free(auio);
1985 }
1986
1987 SBUF_SHOULD("fail gracefully for bad addresses")
1988 {
1989 struct sbuf *s = NULL;
1990 uio_t auio = NULL;
1991 int error = 0;
1992
1993 auio = uio_create(1, 0, UIO_USERSPACE, UIO_WRITE);
1994 uio_addiov(auio, (user_addr_t)0xdeadUL, 123);
1995
1996 s = sbuf_uionew(NULL, auio, &error);
1997 SBUF_ASSERT_EQ(NULL, s);
1998 SBUF_ASSERT_NE(0, error);
1999
2000 uio_free(auio);
2001 }
2002 }
2003
2004 SBUF_TESTING("sbuf_bcopyin")
2005 {
2006 SBUF_SHOULD("succeed when len is zero")
2007 {
2008 struct sbuf *s = NULL;
2009 const void *uptr = (const void *)req->newptr;
2010
2011 s = sbuf_new(NULL, NULL, 16, 0);
2012 SBUF_ASSERT_EQ(0, sbuf_bcopyin(s, uptr, 0));
2013 SBUF_ASSERT_EQ(0, s->s_len);
2014
2015 sbuf_delete(s);
2016 }
2017
2018 SBUF_SHOULD("succeed in the simple case")
2019 {
2020 struct sbuf *s = NULL;
2021 const void *uptr = (const void *)req->newptr;
2022 size_t ulen = req->newlen;
2023
2024 s = sbuf_new(NULL, NULL, 16, 0);
2025 SBUF_ASSERT_EQ(0, sbuf_bcopyin(s, uptr, ulen));
2026 SBUF_ASSERT_EQ(ulen, (size_t)s->s_len);
2027
2028 sbuf_delete(s);
2029 }
2030
2031 SBUF_SHOULD("fail for invalid userland addresses")
2032 {
2033 struct sbuf *s = NULL;
2034 const void *uptr = (const void *)0xdeadUL;
2035 size_t ulen = req->newlen;
2036
2037 s = sbuf_new(NULL, NULL, 16, 0);
2038 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen));
2039 SBUF_ASSERT_EQ(0, s->s_len);
2040
2041 sbuf_delete(s);
2042 }
2043
2044 SBUF_SHOULD("fail for kernel addresses")
2045 {
2046 struct sbuf *s = NULL;
2047 const void *uptr = "abcd";
2048 size_t ulen = 4;
2049
2050 s = sbuf_new(NULL, NULL, 16, 0);
2051 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen));
2052 SBUF_ASSERT_EQ(0, s->s_len);
2053
2054 sbuf_delete(s);
2055 }
2056
2057 SBUF_SHOULD("fail if we don't have capacity for a fixed-len sbuf")
2058 {
2059 struct sbuf *s = NULL;
2060 const void *uptr = (const void *)req->newptr;
2061 size_t ulen = req->newlen;
2062 int len_before;
2063
2064 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
2065 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
2066 len_before = s->s_len;
2067 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen));
2068 SBUF_ASSERT_EQ(len_before, s->s_len);
2069 SBUF_ASSERT(SBUF_ISSET(s, SBUF_OVERFLOWED));
2070
2071 sbuf_delete(s);
2072 }
2073
2074 SBUF_SHOULD("auto-extend if we don't have capacity for an auto-extend sbuf")
2075 {
2076 struct sbuf *s = NULL;
2077 const void *uptr = (const void *)req->newptr;
2078 size_t ulen = req->newlen;
2079 int len_before;
2080
2081 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2082 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
2083 len_before = s->s_len;
2084 SBUF_ASSERT_EQ(0, sbuf_bcopyin(s, uptr, ulen));
2085 SBUF_ASSERT_EQ(len_before + (int)ulen, s->s_len);
2086 SBUF_ASSERT_NOT(SBUF_ISSET(s, SBUF_OVERFLOWED));
2087
2088 sbuf_delete(s);
2089 }
2090
2091 SBUF_SHOULD("fail if overflowed")
2092 {
2093 struct sbuf *s = NULL;
2094 const void *uptr = (const void *)req->newptr;
2095 size_t ulen = req->newlen;
2096
2097 s = sbuf_new(NULL, NULL, 16, 0);
2098 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
2099 SBUF_ASSERT_EQ(-1, sbuf_bcopyin(s, uptr, ulen));
2100
2101 sbuf_delete(s);
2102 }
2103 }
2104
2105 SBUF_TESTING("sbuf_copyin")
2106 {
2107 SBUF_SHOULD("succeed in the simple case")
2108 {
2109 struct sbuf *s = NULL;
2110
2111 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2112 SBUF_ASSERT_EQ(req->newlen + 1, sbuf_copyin(s, (const void *)req->newptr, req->newlen));
2113 SBUF_ASSERT_EQ(req->newlen, s->s_len);
2114
2115 sbuf_delete(s);
2116 }
2117
2118 SBUF_SHOULD("use the sbuf capacity if len is zero")
2119 {
2120 struct sbuf *s = NULL;
2121
2122 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2123 SBUF_ASSERT_EQ(req->newlen + 1, sbuf_copyin(s, (const void *)req->newptr, 0));
2124 SBUF_ASSERT_EQ(req->newlen, s->s_len);
2125
2126 sbuf_delete(s);
2127 }
2128
2129 SBUF_SHOULD("fail if we can't extend the sbuf to accommodate")
2130 {
2131 struct sbuf *s = NULL;
2132
2133 s = sbuf_new(NULL, NULL, 16, SBUF_FIXEDLEN);
2134 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
2135 SBUF_ASSERT_EQ(-1, sbuf_copyin(s, (const void *)req->newptr, req->newlen));
2136
2137 sbuf_delete(s);
2138 }
2139
2140 SBUF_SHOULD("auto-extend the buffer if necessary")
2141 {
2142 struct sbuf *s = NULL;
2143 int len_before;
2144
2145 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2146 SBUF_ASSERT_EQ(0, sbuf_cpy(s, "0123456789abcde"));
2147 len_before = s->s_len;
2148 SBUF_ASSERT_NE(-1, sbuf_copyin(s, (const void *)req->newptr, req->newlen));
2149 SBUF_ASSERT_GT(len_before, s->s_len);
2150
2151 sbuf_delete(s);
2152 }
2153
2154 SBUF_SHOULD("fail if the sbuf is overflowed")
2155 {
2156 struct sbuf *s = NULL;
2157
2158 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2159 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
2160 SBUF_ASSERT_EQ(-1, sbuf_copyin(s, (const void *)req->newptr, req->newlen));
2161
2162 sbuf_delete(s);
2163 }
2164
2165 SBUF_SHOULD("fail gracefully for an invalid address")
2166 {
2167 struct sbuf *s = NULL;
2168
2169 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2170 SBUF_ASSERT_EQ(-1, sbuf_copyin(s, (void *)0xdeadUL, req->newlen));
2171
2172 sbuf_delete(s);
2173 }
2174
2175 SBUF_SHOULD("fail gracefully for a kernel address")
2176 {
2177 struct sbuf *s = NULL;
2178 const char *ptr = "abcd";
2179
2180 s = sbuf_new(NULL, NULL, 16, SBUF_AUTOEXTEND);
2181 SBUF_ASSERT_EQ(-1, sbuf_copyin(s, ptr, strlen(ptr)));
2182
2183 sbuf_delete(s);
2184 }
2185 }
2186
2187 SBUF_TEST_END;
2188 }
2189
2190 SYSCTL_PROC(_kern, OID_AUTO, sbuf_test, CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_MASKED, 0, 0, sysctl_sbuf_tests, "A", "sbuf tests");
2191
2192 #endif /* DEBUG || DEVELOPMENT */