aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Marshall <tdm@cyngn.com>2016-04-08 12:00:28 -0700
committerScott Mertz <scott@cyngn.com>2016-04-13 15:48:15 -0700
commit52e29021d21794b5a464810e057efabe1a1e1543 (patch)
tree8a92dc92198438fdc024f89318aece258a8d53fb
parentb3103a726c0324b12f1c7029d994b088ba5ccc6f (diff)
downloadandroid_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.c27
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);
}