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