Blame posix/wordexp-test.c

Packit Service 82fcde
/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sys/stat.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/mman.h>
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <pwd.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <wordexp.h>
Packit Service 82fcde
#include <libc-pointer-arith.h>
Packit Service 82fcde
#include <dso_handle.h>
Packit Service 82fcde
Packit Service 82fcde
#define IFS " \n\t"
Packit Service 82fcde
Packit Service 82fcde
extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
Packit Service 82fcde
Packit Service 82fcde
static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
Packit Service 82fcde
{
Packit Service 82fcde
  return __register_atfork (prepare, parent, child, __dso_handle);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Number of forks seen.  */
Packit Service 82fcde
static int registered_forks;
Packit Service 82fcde
Packit Service 82fcde
/* For each fork increment the fork count.  */
Packit Service 82fcde
static void
Packit Service 82fcde
register_fork (void)
Packit Service 82fcde
{
Packit Service 82fcde
  registered_forks++;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
struct test_case_struct
Packit Service 82fcde
{
Packit Service 82fcde
  int retval;
Packit Service 82fcde
  const char *env;
Packit Service 82fcde
  const char *words;
Packit Service 82fcde
  int flags;
Packit Service 82fcde
  size_t wordc;
Packit Service 82fcde
  const char *wordv[10];
Packit Service 82fcde
  const char *ifs;
Packit Service 82fcde
} test_case[] =
Packit Service 82fcde
  {
Packit Service 82fcde
    /* Simple word- and field-splitting */
Packit Service 82fcde
    { 0, NULL, "one", 0, 1, { "one", }, IFS },
Packit Service 82fcde
    { 0, NULL, "one two", 0, 2, { "one", "two", }, IFS },
Packit Service 82fcde
    { 0, NULL, "one two three", 0, 3, { "one", "two", "three", }, IFS },
Packit Service 82fcde
    { 0, NULL, " \tfoo\t\tbar ", 0, 2, { "foo", "bar", }, IFS },
Packit Service 82fcde
    { 0, NULL, "red , white blue", 0, 4, { "red", ",", "white", "blue", }, " ," },
Packit Service 82fcde
    { 0, NULL, "one two three", 0, 3, { "one", "two", "three", }, "" },
Packit Service 82fcde
    { 0, NULL, "one \"two three\"", 0, 2, { "one", "two three", }, IFS },
Packit Service 82fcde
    { 0, NULL, "one \"two three\"", 0, 2, { "one", "two three", }, "" },
Packit Service 82fcde
    { 0, "two three", "one \"$var\"", 0, 2, { "one", "two three", }, IFS },
Packit Service 82fcde
    { 0, "two three", "one $var", 0, 3, { "one", "two", "three", }, IFS },
Packit Service 82fcde
    { 0, "two three", "one \"$var\"", 0, 2, { "one", "two three", }, "" },
Packit Service 82fcde
    { 0, "two three", "one $var", 0, 2, { "one", "two three", }, "" },
Packit Service 82fcde
Packit Service 82fcde
    /* The non-whitespace IFS char at the end delimits the second field
Packit Service 82fcde
     * but does NOT start a new field. */
Packit Service 82fcde
    { 0, ":abc:", "$var", 0, 2, { "", "abc", }, ":" },
Packit Service 82fcde
Packit Service 82fcde
    { 0, NULL, "$(echo :abc:)", 0, 2, { "", "abc", }, ":" },
Packit Service 82fcde
    { 0, NULL, "$(echo :abc:\\ )", 0, 2, { "", "abc", }, ": " },
Packit Service 82fcde
    { 0, NULL, "$(echo :abc\\ )", 0, 2, { "", "abc", }, ": " },
Packit Service 82fcde
    { 0, ":abc:", "$(echo $var)", 0, 2, { "", "abc", }, ":" },
Packit Service 82fcde
    { 0, NULL, ":abc:", 0, 1, { ":abc:", }, ":" },
Packit Service 82fcde
    { 0, NULL, "$(echo :abc:)def", 0, 3, { "", "abc", "def", },
Packit Service 82fcde
      ":" },
Packit Service 82fcde
    { 0, NULL, "$(echo abc:de)f", 0, 2, { "abc", "def", }, ":" },
Packit Service 82fcde
    { 0, NULL, "$(echo abc:de)f:ghi", 0, 2, { "abc", "def:ghi", },
Packit Service 82fcde
      ":" },
Packit Service 82fcde
    { 0, NULL, "abc:d$(echo ef:ghi)", 0, 2, { "abc:def", "ghi", },
Packit Service 82fcde
      ":" },
Packit Service 82fcde
    { 0, "abc:", "$var$(echo def:ghi)", 0, 3, { "abc", "def",
Packit Service 82fcde
							  "ghi", }, ":" },
Packit Service 82fcde
    { 0, "abc:d", "$var$(echo ef:ghi)", 0, 3, { "abc", "def",
Packit Service 82fcde
							  "ghi", }, ":" },
Packit Service 82fcde
    { 0, "def:ghi", "$(echo abc:)$var", 0, 3, { "abc", "def",
Packit Service 82fcde
							  "ghi", }, ":" },
Packit Service 82fcde
    { 0, "ef:ghi", "$(echo abc:d)$var", 0, 3, { "abc", "def",
Packit Service 82fcde
							  "ghi", }, ":" },
Packit Service 82fcde
Packit Service 82fcde
    /* Simple parameter expansion */
Packit Service 82fcde
    { 0, "foo", "${var}", 0, 1, { "foo", }, IFS },
Packit Service 82fcde
    { 0, "foo", "$var", 0, 1, { "foo", }, IFS },
Packit Service 82fcde
    { 0, "foo", "\\\"$var\\\"", 0, 1, { "\"foo\"", }, IFS },
Packit Service 82fcde
    { 0, "foo", "%$var%", 0, 1, { "%foo%", }, IFS },
Packit Service 82fcde
    { 0, "foo", "-$var-", 0, 1, { "-foo-", }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Simple quote removal */
Packit Service 82fcde
    { 0, NULL, "\"quoted\"", 0, 1, { "quoted", }, IFS },
Packit Service 82fcde
    { 0, "foo", "\"$var\"\"$var\"", 0, 1, { "foofoo", }, IFS },
Packit Service 82fcde
    { 0, NULL, "'singly-quoted'", 0, 1, { "singly-quoted", }, IFS },
Packit Service 82fcde
    { 0, NULL, "contin\\\nuation", 0, 1, { "continuation", }, IFS },
Packit Service 82fcde
    { 0, NULL, "explicit ''", 0, 2, { "explicit", "", }, IFS },
Packit Service 82fcde
    { 0, NULL, "explicit \"\"", 0, 2, { "explicit", "", }, IFS },
Packit Service 82fcde
    { 0, NULL, "explicit ``", 0, 1, { "explicit", }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Simple command substitution */
Packit Service 82fcde
    { 0, NULL, "$(echo hello)", 0, 1, { "hello", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$( (echo hello) )", 0, 1, { "hello", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((echo hello);(echo there))", 0, 2, { "hello", "there", }, IFS },
Packit Service 82fcde
    { 0, NULL, "`echo one two`", 0, 2, { "one", "two", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$(echo ')')", 0, 1, { ")" }, IFS },
Packit Service 82fcde
    { 0, NULL, "$(echo hello; echo)", 0, 1, { "hello", }, IFS },
Packit Service 82fcde
    { 0, NULL, "a$(echo b)c", 0, 1, { "abc", }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Simple arithmetic expansion */
Packit Service 82fcde
    { 0, NULL, "$((1 + 1))", 0, 1, { "2", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((2-3))", 0, 1, { "-1", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((-1))", 0, 1, { "-1", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$[50+20]", 0, 1, { "70", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$(((2+3)*(4+5)))", 0, 1, { "45", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((010))", 0, 1, { "8" }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((0x10))", 0, 1, { "16" }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((010+0x10))", 0, 1, { "24" }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((-010+0x10))", 0, 1, { "8" }, IFS },
Packit Service 82fcde
    { 0, NULL, "$((-0x10+010))", 0, 1, { "-8" }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Advanced parameter expansion */
Packit Service 82fcde
    { 0, NULL, "${var:-bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var-bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, "", "${var:-bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, "foo", "${var:-bar}", 0, 1, { "foo", }, IFS },
Packit Service 82fcde
    { 0, "", "${var-bar}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var:=bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var=bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, "", "${var:=bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, "foo", "${var:=bar}", 0, 1, { "foo", }, IFS },
Packit Service 82fcde
    { 0, "", "${var=bar}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { 0, "foo", "${var:?bar}", 0, 1, { "foo", }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var:+bar}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var+bar}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { 0, "", "${var:+bar}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { 0, "foo", "${var:+bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, "", "${var+bar}", 0, 1, { "bar", }, IFS },
Packit Service 82fcde
    { 0, "12345", "${#var}", 0, 1, { "5", }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var:-'}'}", 0, 1, { "}", }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var-}", 0, 0, { NULL }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    { 0, "pizza", "${var#${var}}", 0, 0, { NULL }, IFS },
Packit Service 82fcde
    { 0, "pepperoni", "${var%$(echo oni)}", 0, 1, { "pepper" }, IFS },
Packit Service 82fcde
    { 0, "6pack", "${var#$((6))}", 0, 1, { "pack" }, IFS },
Packit Service 82fcde
    { 0, "b*witched", "${var##b*}", 0, 0, { NULL }, IFS },
Packit Service 82fcde
    { 0, "b*witched", "${var##\"b*\"}", 0, 1, { "witched" }, IFS },
Packit Service 82fcde
    { 0, "banana", "${var%na*}", 0, 1, { "bana", }, IFS },
Packit Service 82fcde
    { 0, "banana", "${var%%na*}", 0, 1, { "ba", }, IFS },
Packit Service 82fcde
    { 0, "borabora-island", "${var#*bora}", 0, 1, { "bora-island", }, IFS },
Packit Service 82fcde
    { 0, "borabora-island", "${var##*bora}", 0, 1, { "-island", }, IFS },
Packit Service 82fcde
    { 0, "coconut", "${var##\\*co}", 0, 1, { "coconut", }, IFS },
Packit Service 82fcde
    { 0, "100%", "${var%0%}", 0, 1, { "10" }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Pathname expansion */
Packit Service 82fcde
    { 0, NULL, "???", 0, 2, { "one", "two", }, IFS },
Packit Service 82fcde
    { 0, NULL, "[ot]??", 0, 2, { "one", "two", }, IFS },
Packit Service 82fcde
    { 0, NULL, "t*", 0, 2, { "three", "two", }, IFS },
Packit Service 82fcde
    { 0, NULL, "\"t\"*", 0, 2, { "three", "two", }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Nested constructs */
Packit Service 82fcde
    { 0, "one two", "$var", 0, 2, { "one", "two", }, IFS },
Packit Service 82fcde
    { 0, "one two three", "$var", 0, 3, { "one", "two", "three", }, IFS },
Packit Service 82fcde
    { 0, " \tfoo\t\tbar ", "$var", 0, 2, { "foo", "bar", }, IFS },
Packit Service 82fcde
    { 0, "  red  , white blue", "$var", 0, 3, { "red", "white", "blue", }, ", \n\t" },
Packit Service 82fcde
    { 0, "  red  , white blue", "\"$var\"", 0, 1, { "  red  , white blue", }, ", \n\t" },
Packit Service 82fcde
    { 0, NULL, "\"$(echo hello there)\"", 0, 1, { "hello there", }, IFS },
Packit Service 82fcde
    { 0, NULL, "\"$(echo \"hello there\")\"", 0, 1, { "hello there", }, IFS },
Packit Service 82fcde
    { 0, NULL, "${var=one two} \"$var\"", 0, 3, { "one", "two", "one two", }, IFS },
Packit Service 82fcde
    { 0, "1", "$(( $(echo 3)+$var ))", 0, 1, { "4", }, IFS },
Packit Service 82fcde
    { 0, NULL, "\"$(echo \"*\")\"", 0, 1, { "*", }, IFS },
Packit Service 82fcde
    { 0, NULL, "\"a\n\n$(echo)b\"", 0, 1, { "a\n\nb", }, IFS },
Packit Service 82fcde
    { 0, "foo", "*$var*", 0, 1, { "*foo*", }, IFS },
Packit Service 82fcde
    { 0, "o thr", "*$var*", 0, 2, { "two", "three" }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Different IFS values */
Packit Service 82fcde
    { 0, "a b\tc\nd  ", "$var", 0, 4, { "a", "b", "c", "d" }, NULL /* unset */ },
Packit Service 82fcde
    { 0, "a b\tc d  ", "$var", 0, 1, { "a b\tc d  " }, "" /* `null' */ },
Packit Service 82fcde
    { 0, "a,b c\n, d", "$var", 0, 3, { "a", "b c", " d" }, "\t\n," },
Packit Service 82fcde
Packit Service 82fcde
    /* Other things that should succeed */
Packit Service 82fcde
    { 0, NULL, "\\*\"|&;<>\"\\(\\)\\{\\}", 0, 1, { "*|&;<>(){}", }, IFS },
Packit Service 82fcde
    { 0, "???", "$var", 0, 1, { "???", }, IFS },
Packit Service 82fcde
    { 0, NULL, "$var", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { 0, NULL, "\"\\n\"", 0, 1, { "\\n", }, IFS },
Packit Service 82fcde
    { 0, NULL, "", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Flags not already covered (testit() has special handling for these) */
Packit Service 82fcde
    { 0, NULL, "one two", WRDE_DOOFFS, 2, { "one", "two", }, IFS },
Packit Service 82fcde
    { 0, NULL, "appended", WRDE_APPEND, 3, { "pre1", "pre2", "appended", }, IFS },
Packit Service 82fcde
    { 0, NULL, "appended", WRDE_DOOFFS|WRDE_APPEND, 3, { "pre1", "pre2", "appended", }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    /* Things that should fail */
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "new\nline", 0, 0, { NULL, }, "" /* \n not IFS */ },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "pipe|symbol", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "&ampersand", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "semi;colon", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "less>", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "(open-paren", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "close-paren)", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "{open-brace", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADCHAR, NULL, "close-brace}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_CMDSUB, NULL, "$(ls)", WRDE_NOCMD, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADVAL, NULL, "$var", WRDE_UNDEF, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_BADVAL, NULL, "$9", WRDE_UNDEF, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "$[50+20))", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "${%%noparam}", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "${missing-brace", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "$(for i in)", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
Packit Service 82fcde
    /* Test for CVE-2014-7817. We test 3 combinations of command
Packit Service 82fcde
       substitution inside an arithmetic expression to make sure that
Packit Service 82fcde
       no commands are executed and error is returned.  */
Packit Service 82fcde
    { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
Packit Service 82fcde
    { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
Packit Service 82fcde
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "`\\", 0, 0, { NULL, }, IFS },     /* BZ 18042  */
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "${", 0, 0, { NULL, }, IFS },      /* BZ 18043  */
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "L${a:", 0, 0, { NULL, }, IFS },   /* BZ 18043#c4  */
Packit Service 82fcde
    { WRDE_SYNTAX, NULL, "$[1/0]", WRDE_NOCMD, 0, {NULL, }, IFS }, /* BZ 18100 */
Packit Service 82fcde
Packit Service 82fcde
    { -1, NULL, NULL, 0, 0, { NULL, }, IFS },
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
static int testit (struct test_case_struct *tc);
Packit Service 82fcde
static int tests;
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
command_line_test (const char *words)
Packit Service 82fcde
{
Packit Service 82fcde
  wordexp_t we;
Packit Service 82fcde
  int i;
Packit Service 82fcde
  int retval = wordexp (words, &we, 0);
Packit Service 82fcde
  printf ("wordexp returned %d\n", retval);
Packit Service 82fcde
  for (i = 0; i < we.we_wordc; i++)
Packit Service 82fcde
    printf ("we_wordv[%d] = \"%s\"\n", i, we.we_wordv[i]);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
main (int argc, char *argv[])
Packit Service 82fcde
{
Packit Service 82fcde
  const char *globfile[] = { "one", "two", "three", NULL };
Packit Service 82fcde
  char tmpdir[32];
Packit Service 82fcde
  struct passwd *pw;
Packit Service 82fcde
  const char *cwd;
Packit Service 82fcde
  int test;
Packit Service 82fcde
  int fail = 0;
Packit Service 82fcde
  int i;
Packit Service 82fcde
  struct test_case_struct ts;
Packit Service 82fcde
Packit Service 82fcde
  if (argc > 1)
Packit Service 82fcde
    {
Packit Service 82fcde
      command_line_test (argv[1]);
Packit Service 82fcde
      return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  cwd = getcwd (NULL, 0);
Packit Service 82fcde
Packit Service 82fcde
  /* Set up arena for pathname expansion */
Packit Service 82fcde
  tmpnam (tmpdir);
Packit Service 82fcde
  if (mkdir (tmpdir, S_IRWXU) || chdir (tmpdir))
Packit Service 82fcde
    return -1;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      int fd;
Packit Service 82fcde
Packit Service 82fcde
      for (i = 0; globfile[i]; ++i)
Packit Service 82fcde
	if ((fd = creat (globfile[i], S_IRUSR | S_IWUSR)) == -1
Packit Service 82fcde
	    || close (fd))
Packit Service 82fcde
	  return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* If we are not allowed to do command substitution, we install
Packit Service 82fcde
     fork handlers to verify that no forks happened.  No forks should
Packit Service 82fcde
     happen at all if command substitution is disabled.  */
Packit Service 82fcde
  if (__app_register_atfork (register_fork, NULL, NULL) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("Failed to register fork handler.\n");
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  for (test = 0; test_case[test].retval != -1; test++)
Packit Service 82fcde
    if (testit (&test_case[test]))
Packit Service 82fcde
      ++fail;
Packit Service 82fcde
Packit Service 82fcde
  /* Tilde-expansion tests. */
Packit Service 82fcde
  pw = getpwnam ("root");
Packit Service 82fcde
  if (pw != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      ts.retval = 0;
Packit Service 82fcde
      ts.env = NULL;
Packit Service 82fcde
      ts.words = "~root ";
Packit Service 82fcde
      ts.flags = 0;
Packit Service 82fcde
      ts.wordc = 1;
Packit Service 82fcde
      ts.wordv[0] = pw->pw_dir;
Packit Service 82fcde
      ts.ifs = IFS;
Packit Service 82fcde
Packit Service 82fcde
      if (testit (&ts))
Packit Service 82fcde
	++fail;
Packit Service 82fcde
Packit Service 82fcde
      ts.retval = 0;
Packit Service 82fcde
      ts.env = pw->pw_dir;
Packit Service 82fcde
      ts.words = "${var#~root}x";
Packit Service 82fcde
      ts.flags = 0;
Packit Service 82fcde
      ts.wordc = 1;
Packit Service 82fcde
      ts.wordv[0] = "x";
Packit Service 82fcde
      ts.ifs = IFS;
Packit Service 82fcde
Packit Service 82fcde
      if (testit (&ts))
Packit Service 82fcde
	++fail;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* "~" expands to value of $HOME when HOME is set */
Packit Service 82fcde
Packit Service 82fcde
  setenv ("HOME", "/dummy/home", 1);
Packit Service 82fcde
  ts.retval = 0;
Packit Service 82fcde
  ts.env = NULL;
Packit Service 82fcde
  ts.words = "~ ~/foo";
Packit Service 82fcde
  ts.flags = 0;
Packit Service 82fcde
  ts.wordc = 2;
Packit Service 82fcde
  ts.wordv[0] = "/dummy/home";
Packit Service 82fcde
  ts.wordv[1] = "/dummy/home/foo";
Packit Service 82fcde
  ts.ifs = IFS;
Packit Service 82fcde
Packit Service 82fcde
  if (testit (&ts))
Packit Service 82fcde
    ++fail;
Packit Service 82fcde
Packit Service 82fcde
  /* "~" expands to home dir from passwd file if HOME is not set */
Packit Service 82fcde
Packit Service 82fcde
  pw = getpwuid (getuid ());
Packit Service 82fcde
  if (pw != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      unsetenv ("HOME");
Packit Service 82fcde
      ts.retval = 0;
Packit Service 82fcde
      ts.env = NULL;
Packit Service 82fcde
      ts.words = "~";
Packit Service 82fcde
      ts.flags = 0;
Packit Service 82fcde
      ts.wordc = 1;
Packit Service 82fcde
      ts.wordv[0] = pw->pw_dir;
Packit Service 82fcde
      ts.ifs = IFS;
Packit Service 82fcde
Packit Service 82fcde
      if (testit (&ts))
Packit Service 82fcde
	++fail;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Integer overflow in division.  */
Packit Service 82fcde
  {
Packit Service 82fcde
    static const char *const numbers[] = {
Packit Service 82fcde
      "0",
Packit Service 82fcde
      "1",
Packit Service 82fcde
      "65536",
Packit Service 82fcde
      "2147483648",
Packit Service 82fcde
      "4294967296"
Packit Service 82fcde
      "9223372036854775808",
Packit Service 82fcde
      "18446744073709551616",
Packit Service 82fcde
      "170141183460469231731687303715884105728",
Packit Service 82fcde
      "340282366920938463463374607431768211456",
Packit Service 82fcde
      NULL
Packit Service 82fcde
    };
Packit Service 82fcde
Packit Service 82fcde
    for (const char *const *num = numbers; *num; ++num)
Packit Service 82fcde
      {
Packit Service 82fcde
	wordexp_t p;
Packit Service 82fcde
	char pattern[256];
Packit Service 82fcde
	snprintf (pattern, sizeof (pattern), "$[(-%s)/(-1)]", *num);
Packit Service 82fcde
	int ret = wordexp (pattern, &p, WRDE_NOCMD);
Packit Service 82fcde
	if (ret == 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    if (p.we_wordc != 1 || strcmp (p.we_wordv[0], *num) != 0)
Packit Service 82fcde
	      {
Packit Service 82fcde
		printf ("Integer overflow for \"%s\" failed", pattern);
Packit Service 82fcde
		++fail;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    wordfree (&p);
Packit Service 82fcde
	  }
Packit Service 82fcde
	else if (ret != WRDE_SYNTAX)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    printf ("Integer overflow for \"%s\" failed with %d",
Packit Service 82fcde
		    pattern, ret);
Packit Service 82fcde
	    ++fail;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  puts ("tests completed, now cleaning up");
Packit Service 82fcde
Packit Service 82fcde
  /* Clean up */
Packit Service 82fcde
  for (i = 0; globfile[i]; ++i)
Packit Service 82fcde
    remove (globfile[i]);
Packit Service 82fcde
Packit Service 82fcde
  if (cwd == NULL)
Packit Service 82fcde
    cwd = "..";
Packit Service 82fcde
Packit Service 82fcde
  chdir (cwd);
Packit Service 82fcde
  rmdir (tmpdir);
Packit Service 82fcde
Packit Service 82fcde
  printf ("tests failed: %d\n", fail);
Packit Service 82fcde
Packit Service 82fcde
  return fail != 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static const char *
Packit Service 82fcde
at_page_end (const char *words)
Packit Service 82fcde
{
Packit Service 82fcde
  const int pagesize = getpagesize ();
Packit Service 82fcde
  char *start = mmap (0, 2 * pagesize, PROT_READ|PROT_WRITE,
Packit Service 82fcde
		      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
Packit Service 82fcde
Packit Service 82fcde
  if (start == MAP_FAILED)
Packit Service 82fcde
    return start;
Packit Service 82fcde
Packit Service 82fcde
  if (mprotect (start + pagesize, pagesize, PROT_NONE))
Packit Service 82fcde
    {
Packit Service 82fcde
      munmap (start, 2 * pagesize);
Packit Service 82fcde
      return MAP_FAILED;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Includes terminating NUL.  */
Packit Service 82fcde
  const size_t words_size = strlen (words) + 1;
Packit Service 82fcde
  char *words_start = start + pagesize - words_size;
Packit Service 82fcde
  memcpy (words_start, words, words_size);
Packit Service 82fcde
Packit Service 82fcde
  return words_start;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
testit (struct test_case_struct *tc)
Packit Service 82fcde
{
Packit Service 82fcde
  int retval;
Packit Service 82fcde
  wordexp_t we, sav_we;
Packit Service 82fcde
  char *dummy;
Packit Service 82fcde
  int bzzzt = 0;
Packit Service 82fcde
  int start_offs = 0;
Packit Service 82fcde
  int i;
Packit Service 82fcde
Packit Service 82fcde
  if (tc->env)
Packit Service 82fcde
    setenv ("var", tc->env, 1);
Packit Service 82fcde
  else
Packit Service 82fcde
    unsetenv ("var");
Packit Service 82fcde
Packit Service 82fcde
  if (tc->ifs)
Packit Service 82fcde
    setenv ("IFS", tc->ifs, 1);
Packit Service 82fcde
  else
Packit Service 82fcde
    unsetenv ("IFS");
Packit Service 82fcde
Packit Service 82fcde
  sav_we.we_wordc = 99;
Packit Service 82fcde
  sav_we.we_wordv = &dummy;
Packit Service 82fcde
  sav_we.we_offs = 3;
Packit Service 82fcde
  we = sav_we;
Packit Service 82fcde
Packit Service 82fcde
  printf ("Test %d (%s): ", ++tests, tc->words);
Packit Service 82fcde
  fflush (NULL);
Packit Service 82fcde
  const char *words = at_page_end (tc->words);
Packit Service 82fcde
Packit Service 82fcde
  if (tc->flags & WRDE_NOCMD)
Packit Service 82fcde
    registered_forks = 0;
Packit Service 82fcde
Packit Service 82fcde
  if (tc->flags & WRDE_APPEND)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* initial wordexp() call, to be appended to */
Packit Service 82fcde
      if (wordexp ("pre1 pre2", &we, tc->flags & ~WRDE_APPEND) != 0)
Packit Service 82fcde
        {
Packit Service 82fcde
	  printf ("FAILED setup\n");
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  retval = wordexp (words, &we, tc->flags);
Packit Service 82fcde
Packit Service 82fcde
  if ((tc->flags & WRDE_NOCMD)
Packit Service 82fcde
      && (registered_forks > 0))
Packit Service 82fcde
    {
Packit Service 82fcde
	  printf ("FAILED fork called for WRDE_NOCMD\n");
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (tc->flags & WRDE_DOOFFS)
Packit Service 82fcde
      start_offs = sav_we.we_offs;
Packit Service 82fcde
Packit Service 82fcde
  if (retval != tc->retval || (retval == 0 && we.we_wordc != tc->wordc))
Packit Service 82fcde
    bzzzt = 1;
Packit Service 82fcde
  else if (retval == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      for (i = 0; i < start_offs; ++i)
Packit Service 82fcde
	if (we.we_wordv[i] != NULL)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    bzzzt = 1;
Packit Service 82fcde
	    break;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
      for (i = 0; i < we.we_wordc; ++i)
Packit Service 82fcde
	if (we.we_wordv[i+start_offs] == NULL ||
Packit Service 82fcde
	    strcmp (tc->wordv[i], we.we_wordv[i+start_offs]) != 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    bzzzt = 1;
Packit Service 82fcde
	    break;
Packit Service 82fcde
	  }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (bzzzt)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("FAILED\n");
Packit Service 82fcde
      printf ("Test words: <%s>, need retval %d, wordc %Zd\n",
Packit Service 82fcde
	      tc->words, tc->retval, tc->wordc);
Packit Service 82fcde
      if (start_offs != 0)
Packit Service 82fcde
	printf ("(preceded by %d NULLs)\n", start_offs);
Packit Service 82fcde
      printf ("Got retval %d, wordc %Zd: ", retval, we.we_wordc);
Packit Service 82fcde
      if (retval == 0 || retval == WRDE_NOSPACE)
Packit Service 82fcde
	{
Packit Service 82fcde
	  for (i = 0; i < we.we_wordc + start_offs; ++i)
Packit Service 82fcde
	    if (we.we_wordv[i] == NULL)
Packit Service 82fcde
	      printf ("NULL ");
Packit Service 82fcde
	    else
Packit Service 82fcde
	      printf ("<%s> ", we.we_wordv[i]);
Packit Service 82fcde
	}
Packit Service 82fcde
      printf ("\n");
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (retval != 0 && retval != WRDE_NOSPACE &&
Packit Service 82fcde
	   (we.we_wordc != sav_we.we_wordc ||
Packit Service 82fcde
            we.we_wordv != sav_we.we_wordv ||
Packit Service 82fcde
            we.we_offs != sav_we.we_offs))
Packit Service 82fcde
    {
Packit Service 82fcde
      bzzzt = 1;
Packit Service 82fcde
      printf ("FAILED to restore wordexp_t members\n");
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    printf ("OK\n");
Packit Service 82fcde
Packit Service 82fcde
  if (retval == 0 || retval == WRDE_NOSPACE)
Packit Service 82fcde
    wordfree (&we);
Packit Service 82fcde
Packit Service 82fcde
  const int page_size = getpagesize ();
Packit Service 82fcde
  char *start = (char *) PTR_ALIGN_DOWN (words, page_size);
Packit Service 82fcde
Packit Service 82fcde
  if (munmap (start, 2 * page_size) != 0)
Packit Service 82fcde
    return 1;
Packit Service 82fcde
Packit Service 82fcde
  fflush (NULL);
Packit Service 82fcde
  return bzzzt;
Packit Service 82fcde
}