1/*	$NetBSD: t_exhaust.c,v 1.6 2011/11/16 17:47:19 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.6 2011/11/16 17:47:19 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
49#ifndef REGEX_MAXSIZE
50#define REGEX_MAXSIZE	9999
51#endif
52
53static char *
54mkstr(const char *str, size_t len)
55{
56	size_t slen = strlen(str);
57	char *p = malloc(slen * len + 1);
58	ATF_REQUIRE(p != NULL);
59	for (size_t i = 0; i < len; i++)
60		strcpy(&p[i * slen], str);
61	return p;
62}
63
64static char *
65concat(const char *d, const char *s)
66{
67	size_t dlen = strlen(d);
68	size_t slen = strlen(s);
69	char *p = malloc(dlen + slen + 1);
70
71	ATF_REQUIRE(p != NULL);
72	strcpy(p, d);
73	strcpy(p + dlen, s);
74	return p;
75}
76
77static char *
78p0(size_t len)
79{
80	char *d, *s1, *s2;
81	s1 = mkstr("\\(", len);
82	s2 = concat(s1, ")");
83	free(s1);
84	d = concat("(", s2);
85	free(s2);
86	return d;
87}
88
89static char *
90p1(size_t len)
91{
92	char *d, *s1, *s2, *s3;
93	s1 = mkstr("\\(", 60);
94	s2 = mkstr("(.*)", len);
95	s3 = concat(s1, s2);
96	free(s2);
97	free(s1);
98	s1 = concat(s3, ")");
99	free(s3);
100	d = concat("(", s1);
101	free(s1);
102	return d;
103}
104
105static char *
106ps(const char *m, const char *s, size_t len)
107{
108	char *d, *s1, *s2, *s3;
109	s1 = mkstr(m, len);
110	s2 = mkstr(s, len);
111	s3 = concat(s1, s2);
112	free(s2);
113	free(s1);
114	d = concat("(.?)", s3);
115	free(s3);
116	return d;
117}
118
119static char *
120p2(size_t len)
121{
122	return ps("((.*){0,255}", ")", len);
123}
124
125static char *
126p3(size_t len)
127{
128	return ps("(.\\{0,}", ")", len);
129}
130
131static char *
132p4(size_t len)
133{
134	return ps("((.*){1,255}", ")", len);
135}
136
137static char *
138p5(size_t len)
139{
140	return ps("(", "){1,100}", len);
141}
142
143static char *
144p6(size_t len)
145{
146	char *d, *s1, *s2;
147	s1 = mkstr("(?:(.*)|", len);
148	s2 = concat(s1, "(.*)");
149	free(s1);
150	s1 = mkstr(")", len);
151	d = concat(s2, s1);
152	free(s1);
153	free(s2);
154	return d;
155}
156
157static const struct {
158	char *(*pattern)(size_t);
159	int type;
160} tests[] = {
161	{ p0, REG_EXTENDED },
162	{ p1, REG_EXTENDED },
163	{ p2, REG_EXTENDED },
164	{ p3, REG_EXTENDED },
165	{ p4, REG_EXTENDED },
166	{ p5, REG_EXTENDED },
167	{ p6, REG_BASIC },
168};
169
170ATF_TC(regcomp_too_big);
171
172ATF_TC_HEAD(regcomp_too_big, tc)
173{
174
175	atf_tc_set_md_var(tc, "descr", "Check that large patterns don't"
176	    " crash, but return a proper error code");
177	// libtre needs it.
178	atf_tc_set_md_var(tc, "timeout", "600");
179	atf_tc_set_md_var(tc, "require.memory", "120M");
180}
181
182ATF_TC_BODY(regcomp_too_big, tc)
183{
184	regex_t re;
185	int e;
186
187	for (size_t i = 0; i < __arraycount(tests); i++) {
188		char *d = (*tests[i].pattern)(REGEX_MAXSIZE);
189		e = regcomp(&re, d, tests[i].type);
190		if (e) {
191			char ebuf[1024];
192			(void)regerror(e, &re, ebuf, sizeof(ebuf));
193			ATF_REQUIRE_MSG(e == REG_ESPACE,
194			    "regcomp returned %d (%s) for pattern %zu [%s]", e, ebuf,
195			    i, d);
196			free(d);
197			continue;
198		}
199		free(d);
200		(void)regexec(&re, "aaaaaaaaaaa", 0, NULL, 0);
201		regfree(&re);
202	}
203}
204
205ATF_TP_ADD_TCS(tp)
206{
207
208	ATF_TP_ADD_TC(tp, regcomp_too_big);
209	return atf_no_error();
210}
211