static bool test_strv_split_none(struct torture_context *tctx) { char *strv = NULL; int ret; /* NULL has 0 entries */ ret = strv_split(tctx, &strv, NULL, " "); torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); torture_assert_int_equal(tctx, strv_count(strv), 0, "strv_split() on NULL failed"); TALLOC_FREE(strv); /* Empty string has 0 entries */ ret = strv_split(tctx, &strv, "", " "); torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); torture_assert_int_equal(tctx, strv_count(strv), 0, "strv_split() on \"\" failed"); TALLOC_FREE(strv); /* String containing only separators has 0 entries */ ret = strv_split(tctx, &strv, "abcabcabc", "cba "); torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); torture_assert_int_equal(tctx, strv_count(strv), 0, "strv_split() on seps-only failed"); TALLOC_FREE(strv); return true; }
/* Similar to above but only add/check first 2 chars of each string */ static bool test_strv_addn(struct torture_context *tctx) { const char *data[] = { "foo", "bar", "samba" }; char *strv = NULL; char *t; int i, ret; const int num = ARRAY_SIZE(data); /* Add first 2 chars of each item */ for (i = 0; i < num; i++) { ret = strv_addn(tctx, &strv, data[i], 2); torture_assert(tctx, ret == 0, "strv_add() failed"); } torture_assert_int_equal(tctx, strv_count(strv), num, "strv_count() failed"); /* Check that strv_next() finds the expected values */ t = NULL; for (i = 0; i < num; i++) { t = strv_next(strv, t); torture_assert(tctx, strncmp(t, data[i], 2) == 0, "strv_next() failed"); } return true; }
static bool test_strv_single(struct torture_context *tctx) { const char *data = "foo"; char *strv = NULL; char *t; int ret; /* Add an item */ ret = strv_add(tctx, &strv, data); torture_assert(tctx, ret == 0, "strv_add() failed"); /* Is there 1 item? */ torture_assert_int_equal(tctx, strv_count(strv), 1, "strv_count() failed"); /* Is the expected item the first one? */ t = strv_next(strv, NULL); torture_assert(tctx, strcmp(t, data) == 0, "strv_next() failed"); /* Can the expected item be found? */ t = strv_find(strv, data); torture_assert(tctx, strcmp(t, data) == 0, "strv_next() failed"); /* Delete it */ strv_delete(&strv, t); /* Should have no items */ torture_assert_int_equal(tctx, strv_count(strv), 0, "strv_count() failed"); return true; }
static bool test_strv_empty(struct torture_context *tctx) { /* NULL strv contains 0 entries */ torture_assert_int_equal(tctx, strv_count(NULL), 0, "strv_count() on NULL failed"); /* NULL strv has no next entry */ torture_assert(tctx, strv_next(NULL, NULL) == NULL, "strv_next() on NULL failed"); return true; }
static bool test_strv_multi(struct torture_context *tctx) { const char *data[] = { "foo", "bar", "", "samba", "x"}; char *strv = NULL; char *t; int i, ret; const int num = ARRAY_SIZE(data); /* Add items */ for (i = 0; i < num; i++) { ret = strv_add(tctx, &strv, data[i]); torture_assert(tctx, ret == 0, "strv_add() failed"); } torture_assert_int_equal(tctx, strv_count(strv), num, "strv_count() failed"); /* Check that strv_next() finds the expected values */ t = NULL; for (i = 0; i < num; i++) { t = strv_next(strv, t); torture_assert(tctx, strcmp(t, data[i]) == 0, "strv_next() failed"); } /* Check that strv_next() finds the expected values */ t = NULL; for (i = 0; i < num; i++) { t = strv_next(strv, t); torture_assert(tctx, strcmp(t, data[i]) == 0, "strv_next() failed"); } /* Find each item, delete it, check count */ for (i = 0; i < num; i++) { t = strv_find(strv, data[i]); torture_assert(tctx, strcmp(t, data[i]) == 0, "strv_next() failed"); strv_delete(&strv, t); torture_assert_int_equal(tctx, strv_count(strv), num - i - 1, "strv_delete() failed"); } /* Add items */ for (i = 0; i < num; i++) { ret = strv_add(tctx, &strv, data[i]); torture_assert(tctx, ret == 0, "strv_add() failed"); } torture_assert_int_equal(tctx, strv_count(strv), num, "strv_count() failed"); /* Find items in reverse, delete, check count */ for (i = num - 1; i >= 0; i--) { t = strv_find(strv, data[i]); torture_assert(tctx, strcmp(t, data[i]) == 0, "strv_next() failed"); strv_delete(&strv, t); torture_assert_int_equal(tctx, strv_count(strv), i, "strv_delete() failed"); } return true; }
/* stack: argc argv[0] ... argv[argc] env[0] ... env[n] NULL av[0] ... av[n] NULL */ int elf_stack_setup(struct process *context, user_ptr_t stack, size_t stack_size, char **argv, char **env, struct elf_module *m, struct elf_module *interp) { Elf32Aux aux[30]; int n = 0; int i; char *p; user_ptr_t *init_stack; int pointer_space; int string_space; int offset; user_ptr_t addr; size_t sz; int r; user_ptr_t vdso = 0; r = elf_alloc_vdso(context, &vdso); if (r < 0) return r; memset(&aux, 0, sizeof aux); aux[n].a_type = AT_PHDR; aux[n++].a_value = m->base + m->ehdr.e_phoff; aux[n].a_type = AT_PHENT; aux[n++].a_value = sizeof (Elf32_Phdr); aux[n].a_type = AT_PHNUM; aux[n++].a_value = m->ehdr.e_phnum; if (interp) { aux[n].a_type = AT_BASE; /* interpreter (libc) address */ aux[n++].a_value = (int) interp->base; } aux[n].a_type = AT_FLAGS; aux[n++].a_value = 0; aux[n].a_type = AT_PAGESZ; aux[n++].a_value = pagesize; aux[n].a_type = AT_ENTRY; aux[n++].a_value = (int)m->entry_point; aux[n].a_type = AT_UID; aux[n++].a_value = context->uid; aux[n].a_type = AT_EUID; aux[n++].a_value = context->euid; aux[n].a_type = AT_GID; aux[n++].a_value = context->gid; aux[n].a_type = AT_EGID; aux[n++].a_value = context->egid; aux[n].a_type = AT_SECURE; aux[n++].a_value = 0; aux[n].a_type = AT_SYSINFO; aux[n++].a_value = (int) vdso; assert(n <= sizeof aux/sizeof aux[0]); dprintf("entry is %08x\n", m->entry_point); /* entry, &argc, argv[0..argc-1], NULL, env[0..], NULL, auxv[0..], NULL */ int argc = strv_count(argv); pointer_space = (5 + argc + strv_count(env) + auxv_count(aux)*2); pointer_space *= sizeof (user_ptr_t*); /* env space rounded */ string_space = (strv_length(argv) + strv_length(env) + 3) & ~3; dprintf("%08x bytes for strings\n", string_space); /* * Construct stack in the heap then * write everything to the client in one go */ p = malloc(pointer_space + string_space); if (!p) return -_L(ENOMEM); n = 0; /* base address on local heap */ init_stack = (user_ptr_t*) p; /* base address in client address space */ addr = stack + stack_size - (pointer_space + string_space); /* offset from base address */ offset = pointer_space; /* copy argc, argv arrays onto the allocated memory */ init_stack[n++] = argc; for (i = 0; argv[i]; i++) { dprintf("adding arg %s at %08x\n", argv[i], addr + offset); init_stack[n++] = addr + offset; strcpy(&p[offset], argv[i]); offset += strlen(argv[i]) + 1; } init_stack[n++] = 0; /* gcc optimizes out these assignments if volatile is not used */ for (i = 0; env[i]; i++) { dprintf("adding env %s at %08x\n", env[i], addr + offset); init_stack[n++] = addr + offset; strcpy(&p[offset], env[i]); offset += strlen(env[i]) + 1; } init_stack[n++] = 0; /* set the auxilary vector */ for (i = 0; aux[i].a_type; i++) { init_stack[n++] = aux[i].a_type; init_stack[n++] = aux[i].a_value; } init_stack[n++] = 0; sz = (pointer_space + string_space); r = vm_memcpy_to_process(context, addr, p, sz); free(p); if (r < 0) { printf("vm_memcpy_to_process failed\n"); return r; } context->regs.esp = addr; context->regs.eax = 0; context->regs.ebx = 0; context->regs.ecx = 0; context->regs.edx = 0; context->regs.esi = 0; context->regs.edi = 0; context->regs.ebp = 0; return 0; }