1 /*- 2 * Copyright (c) 2021 Dag-Erling Smørgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifdef HAVE_CONFIG_H 31 # include "config.h" 32 #endif 33 34 #include <sys/types.h> 35 36 #include <errno.h> 37 #include <stdint.h> 38 #include <stdlib.h> 39 40 #include <cryb/test.h> 41 42 #include <security/pam_appl.h> 43 #include "openpam_impl.h" 44 45 static int 46 t_straddch_empty(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED) 47 { 48 char *str; 49 size_t size, len; 50 int ret; 51 52 str = NULL; 53 size = len = SIZE_MAX; 54 ret = t_is_zero_i(openpam_straddch(&str, &size, &len, '\0')); 55 ret &= t_is_not_null(str); 56 ret &= t_is_not_zero_sz(size); 57 ret &= t_is_zero_sz(len); 58 free(str); 59 return ret; 60 } 61 62 static int 63 t_straddch_alloc_fail(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED) 64 { 65 char *str; 66 size_t size, len; 67 int ret; 68 69 str = NULL; 70 size = len = SIZE_MAX; 71 errno = 0; 72 t_malloc_fail = 1; 73 ret = t_compare_i(-1, openpam_straddch(&str, &size, &len, '\0')); 74 t_malloc_fail = 0; 75 ret &= t_compare_i(ENOMEM, errno); 76 ret &= t_is_null(str); 77 ret &= t_compare_sz(SIZE_MAX, size); 78 ret &= t_compare_sz(SIZE_MAX, len); 79 free(str); 80 return ret; 81 } 82 83 static int 84 t_straddch_realloc_fail(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED) 85 { 86 char *str, *_str; 87 size_t size, _size, len, _len; 88 int i, ret; 89 90 // start with an empty string 91 str = NULL; 92 size = len = SIZE_MAX; 93 ret = t_is_zero_i(openpam_straddch(&str, &size, &len, '\0')); 94 ret &= t_is_not_null(str); 95 ret &= t_is_not_zero_sz(size); 96 ret &= t_is_zero_sz(len); 97 if (!ret) 98 goto end; 99 // repeatedly append to it until allocation fails 100 errno = 0; 101 _str = str; 102 _size = size; 103 _len = len; 104 t_malloc_fail = 1; 105 for (i = 0; i < 4096; i++) { 106 if ((ret = openpam_straddch(&str, &size, &len, 'x')) != 0) 107 break; 108 _size = size; 109 _len = len; 110 } 111 t_malloc_fail = 0; 112 ret = t_compare_i(-1, ret); 113 ret &= t_compare_i(ENOMEM, errno); 114 ret &= t_compare_ptr(_str, str); 115 ret &= t_compare_sz(_size, size); 116 ret &= t_compare_sz(_len, len); 117 end: 118 free(str); 119 return ret; 120 } 121 122 static int 123 t_straddch_realloc_ok(char **desc CRYB_UNUSED, void *arg CRYB_UNUSED) 124 { 125 char *str; 126 size_t size, _size, len, _len; 127 int i, ret; 128 129 // start with an empty string 130 str = NULL; 131 size = len = SIZE_MAX; 132 ret = t_is_zero_i(openpam_straddch(&str, &size, &len, '\0')); 133 ret &= t_is_not_null(str); 134 ret &= t_is_not_zero_sz(size); 135 ret &= t_is_zero_sz(len); 136 if (!ret) 137 goto end; 138 // repeatedly append to it until size changes 139 _size = size; 140 _len = len; 141 for (i = ' '; i <= '~'; i++) { // assume ascii 142 if ((ret = openpam_straddch(&str, &size, &len, i)) != 0) 143 break; 144 if (size != _size) 145 break; 146 if (len != _len + 1) 147 break; 148 _len = len; 149 } 150 ret = t_is_zero_i(ret); 151 if (!ret) 152 goto end; 153 ret &= t_compare_sz(_len + 1, len); 154 ret &= t_compare_sz(_size * 2, size); 155 ret &= t_compare_i(i, str[_len]); 156 ret &= t_is_zero_i(str[len]); 157 end: 158 free(str); 159 return ret; 160 } 161 162 163 /*************************************************************************** 164 * Boilerplate 165 */ 166 167 static int 168 t_prepare(int argc CRYB_UNUSED, char *argv[] CRYB_UNUSED) 169 { 170 171 t_add_test(t_straddch_empty, NULL, "empty string"); 172 t_add_test(t_straddch_alloc_fail, NULL, "allocation failure"); 173 t_add_test(t_straddch_realloc_fail, NULL, "reallocation failure"); 174 t_add_test(t_straddch_realloc_ok, NULL, "reallocation success"); 175 return (0); 176 } 177 178 int 179 main(int argc, char *argv[]) 180 { 181 182 t_main(t_prepare, NULL, argc, argv); 183 } 184