summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2011-02-10 21:32:00 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2011-02-10 21:32:00 +0000
commitbaeeb41ea912884bc9edd4d9948fecf4fce85798 (patch)
treeeda0d1412f66a812dc115947bf62de208b2293d5 /lib/libc
parent1621b63b7d6f8b26cd58be84a18ca219b2ed981d (diff)
Put a limit on recursion during matching, and reject input of size greater
or equal PATH_MAX. Based on similar fix made in NetBSD. ok miod@ millert@
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/fnmatch.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c
index 2388f826382..a005013aab6 100644
--- a/lib/libc/gen/fnmatch.c
+++ b/lib/libc/gen/fnmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fnmatch.c,v 1.14 2008/10/01 23:04:13 millert Exp $ */
+/* $OpenBSD: fnmatch.c,v 1.15 2011/02/10 21:31:59 stsp Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <string.h>
#include <fnmatch.h>
+#include <limits.h>
#include "charclass.h"
@@ -50,15 +51,38 @@
#define RANGE_NOMATCH 0
#define RANGE_ERROR (-1)
+/* Limit of recursion during matching attempts. */
+#define __FNM_MAX_RECUR 64
+
static int rangematch(const char *, char, int, char **);
static int classmatch(const char *, char, int, const char **);
+static int __fnmatch(const char *, const char *, int, int);
int
fnmatch(const char *pattern, const char *string, int flags)
{
+ int e;
+
+ if (strnlen(pattern, PATH_MAX) == PATH_MAX ||
+ strnlen(string, PATH_MAX) == PATH_MAX)
+ return (FNM_NOMATCH);
+
+ e = __fnmatch(pattern, string, flags, __FNM_MAX_RECUR);
+ if (e == -1)
+ e = FNM_NOMATCH;
+ return (e);
+}
+
+static int
+__fnmatch(const char *pattern, const char *string, int flags, int recur)
+{
const char *stringstart;
char *newp;
char c, test;
+ int e;
+
+ if (recur-- == 0)
+ return (-1);
for (stringstart = string;;)
switch (c = *pattern++) {
@@ -104,8 +128,10 @@ fnmatch(const char *pattern, const char *string, int flags)
/* General case, use recursion. */
while ((test = *string) != EOS) {
- if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
- return (0);
+ e = __fnmatch(pattern, string,
+ flags & ~FNM_PERIOD, recur);
+ if (e != FNM_NOMATCH)
+ return (e);
if (test == '/' && (flags & FNM_PATHNAME))
break;
++string;