diff options
author | Tom Marshall <tdm@cyngn.com> | 2016-04-08 12:00:28 -0700 |
---|---|---|
committer | Scott Mertz <scott@cyngn.com> | 2016-04-13 15:48:15 -0700 |
commit | 52e29021d21794b5a464810e057efabe1a1e1543 (patch) | |
tree | 8a92dc92198438fdc024f89318aece258a8d53fb | |
parent | b3103a726c0324b12f1c7029d994b088ba5ccc6f (diff) | |
download | android_external_toybox-stable/cm-13.0-ZNH2K.tar.gz android_external_toybox-stable/cm-13.0-ZNH2K.tar.bz2 android_external_toybox-stable/cm-13.0-ZNH2K.zip |
toybox: find: Fix segfault when using -iname/-ipath with -execstable/cm-13.0-ZNH2KBstable/cm-13.0-ZNH2K
iname/ipath use the argdata list to store names (type char*) on the initial
argument parsing pass and then use these on subsequent passes with entries
returned from dirtree_flagread. exec/execdir also use the argdata list to
store its arguments (type struct exec_range*). Thus, it is imperative that
each value pushed onto the list be popped in exactly the same order.
Failure to do this results in pointers from the list being cast to an
incorrect type and segfaults ensue.
During subsequent passes when using an "or" predicate, the current code in
iname/ipath fails to pop the same values that it pushed when the LHS
evaluates to true. This is because the "or" code sets active==0 which then
sets check==0 when evaluating the RHS, and the RHS name is not popped.
Subsequent usage of "exec" will try to pop this value as an argument list
and segfault.
This could be fixed by making usage of argdata consistent in iname/ipath.
However, it does not appear necessary to use argdata at all. So remove
it and lowercase the pattern inplace. This avoids the segfault and also
avoids unnecessary heap allocs.
CYNGNOS-2337
Change-Id: Icb171b90a60bc6cf5629f87ed5966b4d26e22b28
(cherry picked from commit d5de71798489bf4cc2c1e89c0b0f2768a3b2ae47)
-rw-r--r-- | toys/posix/find.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/toys/posix/find.c b/toys/posix/find.c index a9c35f41..b54fc68c 100644 --- a/toys/posix/find.c +++ b/toys/posix/find.c @@ -315,22 +315,21 @@ static int do_find(struct dirtree *new) || !strcmp(s, "path") || !strcmp(s, "ipath")) { int i = (*s == 'i'); - char *arg = ss[1], *path = 0, *name = new ? new->name : arg; - - // Handle path expansion and case flattening - if (new && s[i] == 'p') name = path = dirtree_path(new, 0); - if (i) { - if (check || !new) { - if (name) name = strlower(name); - if (!new) { - dlist_add(&TT.argdata, name); - free(path); - } else arg = ((struct double_list *)llist_pop(&argdata))->data; - } - } + if (i && !new) { + char *p; + for (p = ss[1]; *p; ++p) { + *p = tolower(*p); + } + } if (check) { - test = !fnmatch(arg, name, FNM_PATHNAME*(s[i] == 'p')); + char *path = 0, *name = new->name; + + // Handle path expansion and case flattening + if (s[i] == 'p') name = path = dirtree_path(new, 0); + if (i) name = strlower(name); + + test = !fnmatch(ss[1], name, FNM_PATHNAME*(s[i] == 'p')); free(path); if (i) free(name); } |