Module Name: src Committed By: christos Date: Sun Oct 9 18:21:09 UTC 2011
Modified Files: src/tests/lib/libc/regex: Makefile Added Files: src/tests/lib/libc/regex: t_exhaust.c Log Message: Add a test to check for DoS attacks against regcomp/regexec. From Maksymilian Arciemowicz. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libc/regex/Makefile cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/regex/t_exhaust.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/lib/libc/regex/Makefile diff -u src/tests/lib/libc/regex/Makefile:1.1 src/tests/lib/libc/regex/Makefile:1.2 --- src/tests/lib/libc/regex/Makefile:1.1 Sat Jan 8 20:00:40 2011 +++ src/tests/lib/libc/regex/Makefile Sun Oct 9 14:21:08 2011 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.1 2011/01/09 01:00:40 pgoyette Exp $ +# $NetBSD: Makefile,v 1.2 2011/10/09 18:21:08 christos Exp $ MKMAN= no @@ -12,6 +12,7 @@ SRCS= main.c split.c debug.c CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libc/regex TESTS_SH= t_regex +TESTS_C= t_exhaust FILESDIR= ${TESTSDIR}/data FILES+= README Added files: Index: src/tests/lib/libc/regex/t_exhaust.c diff -u /dev/null src/tests/lib/libc/regex/t_exhaust.c:1.1 --- /dev/null Sun Oct 9 14:21:09 2011 +++ src/tests/lib/libc/regex/t_exhaust.c Sun Oct 9 14:21:08 2011 @@ -0,0 +1,196 @@ +/* $NetBSD: t_exhaust.c,v 1.1 2011/10/09 18:21:08 christos Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_exhaust.c,v 1.1 2011/10/09 18:21:08 christos Exp $"); + +#include <stdio.h> +#include <regex.h> +#include <string.h> +#include <stdlib.h> +#include <err.h> +#include <atf-c.h> + + +static char * +mkstr(const char *str, size_t len) +{ + size_t slen = strlen(str); + char *p = malloc(slen * len + 1); + if (p == NULL) + err(1, "malloc"); + for (size_t i = 0; i < len; i++) + strcpy(&p[i * slen], str); + return p; +} + +static char * +concat(const char *d, const char *s) +{ + size_t dlen = strlen(d); + size_t slen = strlen(s); + char *p = malloc(dlen + slen + 1); + strcpy(p, d); + strcpy(p + dlen, s); + return p; +} + +static char * +p0(size_t len) +{ + char *d, *s1, *s2; + s1 = mkstr("\\(", len); + s2 = concat(s1, ")"); + free(s1); + d = concat("(", s2); + free(s2); + return d; +} + +static char * +p1(size_t len) +{ + char *d, *s1, *s2, *s3; + s1 = mkstr("\\(", 60); + s2 = mkstr("(.*)", len); + s3 = concat(s1, s2); + free(s2); + free(s1); + s1 = concat(s3, ")"); + free(s3); + d = concat("(", s1); + free(s1); + return d; +} + +static char * +ps(const char *m, const char *s, size_t len) +{ + char *d, *s1, *s2, *s3; + s1 = mkstr(m, len); + s2 = mkstr(s, len); + s3 = concat(s1, s2); + free(s2); + free(s1); + d = concat("(.?)", s3); + free(s3); + return d; +} + +static char * +p2(size_t len) +{ + return ps("((.*){0,255}", ")", len); +} + +static char * +p3(size_t len) +{ + return ps("(.\\{0,}", ")", len); +} + +static char * +p4(size_t len) +{ + return ps("((.*){1,255}", ")", len); +} + +static char * +p5(size_t len) +{ + return ps("(", "){1,100}", len); +} + +static char * +p6(size_t len) +{ + char *d, *s1, *s2; + s1 = mkstr("(?:(.*)|", len); + s2 = concat(s1, "(.*)"); + free(s1); + s1 = mkstr(")", len); + d = concat(s2, s1); + free(s1); + free(s2); + return d; +} + +static char *(*patterns[])(size_t) = { + p0, + p1, + p2, + p3, + p4, + p5, + p6, +}; + +ATF_TC(regcomp_too_big); + +ATF_TC_HEAD(regcomp_too_big, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check that large patterns don't" + " crash, but return a proper error code"); +} + +ATF_TC_BODY(regcomp_too_big, tc) +{ + regex_t re; + int e; + + for (size_t i = 0; i < __arraycount(patterns); i++) { + char *d = (*patterns[i])(9999); + e = regcomp(&re, d, i == 6 ? REG_BASIC : REG_EXTENDED); + free(d); + if (e != 0) + ATF_REQUIRE_MSG(e == REG_ESPACE, + "regcomp returned %d for pattern %zu", e, i); + if (e) + continue; + e = regexec(&re, "aaaaaaaa", 0, NULL, 0); + regfree(&re); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, regcomp_too_big); + return atf_no_error(); +}