1314817Sngie/*	$NetBSD: t_exhaust.c,v 1.8 2017/01/14 00:50:56 christos Exp $	*/
2272343Sngie
3272343Sngie/*-
4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc.
5272343Sngie * All rights reserved.
6272343Sngie *
7272343Sngie * This code is derived from software contributed to The NetBSD Foundation
8272343Sngie * by Christos Zoulas.
9272343Sngie *
10272343Sngie * Redistribution and use in source and binary forms, with or without
11272343Sngie * modification, are permitted provided that the following conditions
12272343Sngie * are met:
13272343Sngie * 1. Redistributions of source code must retain the above copyright
14272343Sngie *    notice, this list of conditions and the following disclaimer.
15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
16272343Sngie *    notice, this list of conditions and the following disclaimer in the
17272343Sngie *    documentation and/or other materials provided with the distribution.
18272343Sngie * 3. All advertising materials mentioning features or use of this software
19272343Sngie *    must display the following acknowledgement:
20272343Sngie *        This product includes software developed by the NetBSD
21272343Sngie *        Foundation, Inc. and its contributors.
22272343Sngie * 4. Neither the name of The NetBSD Foundation nor the names of its
23272343Sngie *    contributors may be used to endorse or promote products derived
24272343Sngie *    from this software without specific prior written permission.
25272343Sngie *
26272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29272343Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36272343Sngie * POSSIBILITY OF SUCH DAMAGE.
37272343Sngie */
38272343Sngie
39272343Sngie#include <sys/cdefs.h>
40314817Sngie__RCSID("$NetBSD: t_exhaust.c,v 1.8 2017/01/14 00:50:56 christos Exp $");
41272343Sngie
42314817Sngie#include <sys/resource.h>
43314817Sngie#include <atf-c.h>
44314817Sngie#include <err.h>
45314817Sngie#include <regex.h>
46272343Sngie#include <stdio.h>
47314817Sngie#include <stdlib.h>
48272343Sngie#include <string.h>
49272343Sngie
50272343Sngie#ifndef REGEX_MAXSIZE
51272343Sngie#define REGEX_MAXSIZE	9999
52272343Sngie#endif
53272343Sngie
54272343Sngiestatic char *
55272343Sngiemkstr(const char *str, size_t len)
56272343Sngie{
57272343Sngie	size_t slen = strlen(str);
58272343Sngie	char *p = malloc(slen * len + 1);
59272343Sngie	ATF_REQUIRE(p != NULL);
60272343Sngie	for (size_t i = 0; i < len; i++)
61272343Sngie		strcpy(&p[i * slen], str);
62272343Sngie	return p;
63272343Sngie}
64272343Sngie
65272343Sngiestatic char *
66272343Sngieconcat(const char *d, const char *s)
67272343Sngie{
68272343Sngie	size_t dlen = strlen(d);
69272343Sngie	size_t slen = strlen(s);
70272343Sngie	char *p = malloc(dlen + slen + 1);
71272343Sngie
72272343Sngie	ATF_REQUIRE(p != NULL);
73272343Sngie	strcpy(p, d);
74272343Sngie	strcpy(p + dlen, s);
75272343Sngie	return p;
76272343Sngie}
77272343Sngie
78272343Sngiestatic char *
79272343Sngiep0(size_t len)
80272343Sngie{
81272343Sngie	char *d, *s1, *s2;
82272343Sngie	s1 = mkstr("\\(", len);
83272343Sngie	s2 = concat(s1, ")");
84272343Sngie	free(s1);
85272343Sngie	d = concat("(", s2);
86272343Sngie	free(s2);
87272343Sngie	return d;
88272343Sngie}
89272343Sngie
90272343Sngiestatic char *
91272343Sngiep1(size_t len)
92272343Sngie{
93272343Sngie	char *d, *s1, *s2, *s3;
94272343Sngie	s1 = mkstr("\\(", 60);
95272343Sngie	s2 = mkstr("(.*)", len);
96272343Sngie	s3 = concat(s1, s2);
97272343Sngie	free(s2);
98272343Sngie	free(s1);
99272343Sngie	s1 = concat(s3, ")");
100272343Sngie	free(s3);
101272343Sngie	d = concat("(", s1);
102272343Sngie	free(s1);
103272343Sngie	return d;
104272343Sngie}
105272343Sngie
106272343Sngiestatic char *
107272343Sngieps(const char *m, const char *s, size_t len)
108272343Sngie{
109272343Sngie	char *d, *s1, *s2, *s3;
110272343Sngie	s1 = mkstr(m, len);
111272343Sngie	s2 = mkstr(s, len);
112272343Sngie	s3 = concat(s1, s2);
113272343Sngie	free(s2);
114272343Sngie	free(s1);
115272343Sngie	d = concat("(.?)", s3);
116272343Sngie	free(s3);
117272343Sngie	return d;
118272343Sngie}
119272343Sngie
120272343Sngiestatic char *
121272343Sngiep2(size_t len)
122272343Sngie{
123272343Sngie	return ps("((.*){0,255}", ")", len);
124272343Sngie}
125272343Sngie
126272343Sngiestatic char *
127272343Sngiep3(size_t len)
128272343Sngie{
129272343Sngie	return ps("(.\\{0,}", ")", len);
130272343Sngie}
131272343Sngie
132272343Sngiestatic char *
133272343Sngiep4(size_t len)
134272343Sngie{
135272343Sngie	return ps("((.*){1,255}", ")", len);
136272343Sngie}
137272343Sngie
138272343Sngiestatic char *
139272343Sngiep5(size_t len)
140272343Sngie{
141272343Sngie	return ps("(", "){1,100}", len);
142272343Sngie}
143272343Sngie
144272343Sngiestatic char *
145272343Sngiep6(size_t len)
146272343Sngie{
147272343Sngie	char *d, *s1, *s2;
148272343Sngie	s1 = mkstr("(?:(.*)|", len);
149272343Sngie	s2 = concat(s1, "(.*)");
150272343Sngie	free(s1);
151272343Sngie	s1 = mkstr(")", len);
152272343Sngie	d = concat(s2, s1);
153272343Sngie	free(s1);
154272343Sngie	free(s2);
155272343Sngie	return d;
156272343Sngie}
157272343Sngie
158272343Sngiestatic const struct {
159272343Sngie	char *(*pattern)(size_t);
160272343Sngie	int type;
161272343Sngie} tests[] = {
162272343Sngie	{ p0, REG_EXTENDED },
163272343Sngie	{ p1, REG_EXTENDED },
164272343Sngie	{ p2, REG_EXTENDED },
165272343Sngie	{ p3, REG_EXTENDED },
166272343Sngie	{ p4, REG_EXTENDED },
167272343Sngie	{ p5, REG_EXTENDED },
168272343Sngie	{ p6, REG_BASIC },
169272343Sngie};
170272343Sngie
171272343SngieATF_TC(regcomp_too_big);
172272343Sngie
173272343SngieATF_TC_HEAD(regcomp_too_big, tc)
174272343Sngie{
175272343Sngie
176272343Sngie	atf_tc_set_md_var(tc, "descr", "Check that large patterns don't"
177272343Sngie	    " crash, but return a proper error code");
178272343Sngie	// libtre needs it.
179272343Sngie	atf_tc_set_md_var(tc, "timeout", "600");
180276478Sngie	atf_tc_set_md_var(tc, "require.memory", "64M");
181272343Sngie}
182272343Sngie
183272343SngieATF_TC_BODY(regcomp_too_big, tc)
184272343Sngie{
185272343Sngie	regex_t re;
186276478Sngie	struct rlimit limit;
187272343Sngie	int e;
188272343Sngie
189276478Sngie	limit.rlim_cur = limit.rlim_max = 64 * 1024 * 1024;
190276478Sngie	ATF_REQUIRE(setrlimit(RLIMIT_VMEM, &limit) != -1);
191272343Sngie	for (size_t i = 0; i < __arraycount(tests); i++) {
192272343Sngie		char *d = (*tests[i].pattern)(REGEX_MAXSIZE);
193272343Sngie		e = regcomp(&re, d, tests[i].type);
194272343Sngie		if (e) {
195272343Sngie			char ebuf[1024];
196272343Sngie			(void)regerror(e, &re, ebuf, sizeof(ebuf));
197272343Sngie			ATF_REQUIRE_MSG(e == REG_ESPACE,
198272343Sngie			    "regcomp returned %d (%s) for pattern %zu [%s]", e, ebuf,
199272343Sngie			    i, d);
200272343Sngie			free(d);
201272343Sngie			continue;
202272343Sngie		}
203272343Sngie		free(d);
204272343Sngie		(void)regexec(&re, "aaaaaaaaaaa", 0, NULL, 0);
205272343Sngie		regfree(&re);
206272343Sngie	}
207272343Sngie}
208272343Sngie
209272343SngieATF_TP_ADD_TCS(tp)
210272343Sngie{
211272343Sngie
212272343Sngie	ATF_TP_ADD_TC(tp, regcomp_too_big);
213272343Sngie	return atf_no_error();
214272343Sngie}
215