1 /* $NetBSD: t_exhaust.c,v 1.7 2011/11/16 18:37:31 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __RCSID("$NetBSD: t_exhaust.c,v 1.7 2011/11/16 18:37:31 christos Exp $"); 41 42 #include <stdio.h> 43 #include <regex.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #include <err.h> 47 #include <atf-c.h> 48 #if defined(__FreeBSD__) 49 #include <sys/resource.h> 50 #endif 51 52 #ifndef REGEX_MAXSIZE 53 #define REGEX_MAXSIZE 9999 54 #endif 55 56 static char * 57 mkstr(const char *str, size_t len) 58 { 59 size_t slen = strlen(str); 60 char *p = malloc(slen * len + 1); 61 ATF_REQUIRE(p != NULL); 62 for (size_t i = 0; i < len; i++) 63 strcpy(&p[i * slen], str); 64 return p; 65 } 66 67 static char * 68 concat(const char *d, const char *s) 69 { 70 size_t dlen = strlen(d); 71 size_t slen = strlen(s); 72 char *p = malloc(dlen + slen + 1); 73 74 ATF_REQUIRE(p != NULL); 75 strcpy(p, d); 76 strcpy(p + dlen, s); 77 return p; 78 } 79 80 static char * 81 p0(size_t len) 82 { 83 char *d, *s1, *s2; 84 s1 = mkstr("\\(", len); 85 s2 = concat(s1, ")"); 86 free(s1); 87 d = concat("(", s2); 88 free(s2); 89 return d; 90 } 91 92 static char * 93 p1(size_t len) 94 { 95 char *d, *s1, *s2, *s3; 96 s1 = mkstr("\\(", 60); 97 s2 = mkstr("(.*)", len); 98 s3 = concat(s1, s2); 99 free(s2); 100 free(s1); 101 s1 = concat(s3, ")"); 102 free(s3); 103 d = concat("(", s1); 104 free(s1); 105 return d; 106 } 107 108 static char * 109 ps(const char *m, const char *s, size_t len) 110 { 111 char *d, *s1, *s2, *s3; 112 s1 = mkstr(m, len); 113 s2 = mkstr(s, len); 114 s3 = concat(s1, s2); 115 free(s2); 116 free(s1); 117 d = concat("(.?)", s3); 118 free(s3); 119 return d; 120 } 121 122 static char * 123 p2(size_t len) 124 { 125 return ps("((.*){0,255}", ")", len); 126 } 127 128 static char * 129 p3(size_t len) 130 { 131 return ps("(.\\{0,}", ")", len); 132 } 133 134 static char * 135 p4(size_t len) 136 { 137 return ps("((.*){1,255}", ")", len); 138 } 139 140 static char * 141 p5(size_t len) 142 { 143 return ps("(", "){1,100}", len); 144 } 145 146 static char * 147 p6(size_t len) 148 { 149 char *d, *s1, *s2; 150 s1 = mkstr("(?:(.*)|", len); 151 s2 = concat(s1, "(.*)"); 152 free(s1); 153 s1 = mkstr(")", len); 154 d = concat(s2, s1); 155 free(s1); 156 free(s2); 157 return d; 158 } 159 160 static const struct { 161 char *(*pattern)(size_t); 162 int type; 163 } tests[] = { 164 { p0, REG_EXTENDED }, 165 { p1, REG_EXTENDED }, 166 { p2, REG_EXTENDED }, 167 { p3, REG_EXTENDED }, 168 { p4, REG_EXTENDED }, 169 { p5, REG_EXTENDED }, 170 { p6, REG_BASIC }, 171 }; 172 173 ATF_TC(regcomp_too_big); 174 175 ATF_TC_HEAD(regcomp_too_big, tc) 176 { 177 178 atf_tc_set_md_var(tc, "descr", "Check that large patterns don't" 179 " crash, but return a proper error code"); 180 // libtre needs it. 181 atf_tc_set_md_var(tc, "timeout", "600"); 182 #if defined(__FreeBSD__) 183 atf_tc_set_md_var(tc, "require.memory", "64M"); 184 #else 185 atf_tc_set_md_var(tc, "require.memory", "120M"); 186 #endif 187 } 188 189 ATF_TC_BODY(regcomp_too_big, tc) 190 { 191 regex_t re; 192 #if defined(__FreeBSD__) 193 struct rlimit limit; 194 #endif 195 int e; 196 197 #if defined(__FreeBSD__) 198 limit.rlim_cur = limit.rlim_max = 64 * 1024 * 1024; 199 ATF_REQUIRE(setrlimit(RLIMIT_VMEM, &limit) != -1); 200 #endif 201 for (size_t i = 0; i < __arraycount(tests); i++) { 202 char *d = (*tests[i].pattern)(REGEX_MAXSIZE); 203 e = regcomp(&re, d, tests[i].type); 204 if (e) { 205 char ebuf[1024]; 206 (void)regerror(e, &re, ebuf, sizeof(ebuf)); 207 ATF_REQUIRE_MSG(e == REG_ESPACE, 208 "regcomp returned %d (%s) for pattern %zu [%s]", e, ebuf, 209 i, d); 210 free(d); 211 continue; 212 } 213 free(d); 214 (void)regexec(&re, "aaaaaaaaaaa", 0, NULL, 0); 215 regfree(&re); 216 } 217 } 218 219 ATF_TP_ADD_TCS(tp) 220 { 221 222 ATF_TP_ADD_TC(tp, regcomp_too_big); 223 return atf_no_error(); 224 } 225