From e128a50e35eb4eabcf234ada07f07b8749b5e49c Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 22 Sep 2011 21:22:21 +1000 Subject: - djm@cvs.openbsd.org 2011/09/22 06:27:29 [glob.c] fix GLOB_KEEPSTAT without GLOB_NOSORT; the implicit sort was being applied only to the gl_pathv vector and not the corresponding gl_statv array. reported in OpenSSH bz#1935; feedback and okay matthew@ --- openbsd-compat/glob.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 85fccf4d1..742b4b954 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c @@ -1,4 +1,4 @@ -/* $OpenBSD: glob.c,v 1.37 2011/09/20 10:18:46 stsp Exp $ */ +/* $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 djm Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -133,16 +133,22 @@ typedef char Char; #define GLOB_LIMIT_STAT 128 #define GLOB_LIMIT_READDIR 16384 +/* Limit of recursion during matching attempts. */ +#define GLOB_LIMIT_RECUR 64 + struct glob_lim { size_t glim_malloc; size_t glim_stat; size_t glim_readdir; }; -/* Limit of recursion during matching attempts. */ -#define GLOB_LIMIT_RECUR 64 +struct glob_path_stat { + char *gps_path; + struct stat *gps_stat; +}; static int compare(const void *, const void *); +static int compare_gps(const void *, const void *); static int g_Ctoc(const Char *, char *, u_int); static int g_lstat(Char *, struct stat *, glob_t *); static DIR *g_opendir(Char *, glob_t *); @@ -555,9 +561,32 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) else return(GLOB_NOMATCH); } - if (!(pglob->gl_flags & GLOB_NOSORT)) - qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, - pglob->gl_pathc - oldpathc, sizeof(char *), compare); + if (!(pglob->gl_flags & GLOB_NOSORT)) { + if ((pglob->gl_flags & GLOB_KEEPSTAT)) { + /* Keep the paths and stat info synced during sort */ + struct glob_path_stat *path_stat; + int i; + int n = pglob->gl_pathc - oldpathc; + int o = pglob->gl_offs + oldpathc; + + if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL) + return GLOB_NOSPACE; + for (i = 0; i < n; i++) { + path_stat[i].gps_path = pglob->gl_pathv[o + i]; + path_stat[i].gps_stat = pglob->gl_statv[o + i]; + } + qsort(path_stat, n, sizeof(*path_stat), compare_gps); + for (i = 0; i < n; i++) { + pglob->gl_pathv[o + i] = path_stat[i].gps_path; + pglob->gl_statv[o + i] = path_stat[i].gps_stat; + } + free(path_stat); + } else { + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), + compare); + } + } return(0); } @@ -567,6 +596,15 @@ compare(const void *p, const void *q) return(strcmp(*(char **)p, *(char **)q)); } +static int +compare_gps(const void *_p, const void *_q) +{ + const struct glob_path_stat *p = (const struct glob_path_stat *)_p; + const struct glob_path_stat *q = (const struct glob_path_stat *)_q; + + return(strcmp(p->gps_path, q->gps_path)); +} + static int glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { -- cgit v1.2.3