posix: Remove alloca usage for internal fnmatch implementation
[platform/upstream/glibc.git] / posix / tst-wordexp-nocmd.c
1 /* Test for (lack of) command execution in wordexp.
2    Copyright (C) 1997-2021 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 /* This test optionally counts PIDs in a PID namespace to detect
20    forks.  Without kernel support for that, it will merely look at the
21    error codes from wordexp to check that no command execution
22    happens.  */
23
24 #include <sched.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <support/check.h>
29 #include <support/namespace.h>
30 #include <support/xunistd.h>
31 #include <wordexp.h>
32
33 /* Set to true if the test runs in a PID namespace and can therefore
34    use next_pid below.  */
35 static bool pid_tests_supported;
36
37 /* The next PID, as returned from next_pid below.  Only meaningful if
38    pid_tests_supported.  */
39 static pid_t expected_pid;
40
41 /* Allocate the next PID and return it.  The process is terminated.
42    Note that the test itself advances the next PID.  */
43 static pid_t
44 next_pid (void)
45 {
46   pid_t pid = xfork ();
47   if (pid == 0)
48     _exit (0);
49   xwaitpid (pid, NULL, 0);
50   return pid;
51 }
52
53 /* Check that evaluating PATTERN with WRDE_NOCMD results in
54    EXPECTED_ERROR.  */
55 static void
56 expect_failure (const char *pattern, int expected_error)
57 {
58   printf ("info: testing pattern: %s\n", pattern);
59   wordexp_t w;
60   TEST_COMPARE (wordexp (pattern, &w, WRDE_NOCMD), expected_error);
61   if (pid_tests_supported)
62     TEST_COMPARE (expected_pid++, next_pid ());
63 }
64
65 /* Run all the tests.  Invoked with different IFS values.  */
66 static void
67 run_tests (void)
68 {
69   /* Integer overflow in division.  */
70   {
71     static const char *const numbers[] = {
72       "0",
73       "1",
74       "65536",
75       "2147483648",
76       "4294967296"
77       "9223372036854775808",
78       "18446744073709551616",
79       "170141183460469231731687303715884105728",
80       "340282366920938463463374607431768211456",
81       NULL
82     };
83
84     for (const char *const *num = numbers; *num != NULL; ++num)
85       {
86         wordexp_t w;
87         char pattern[256];
88         snprintf (pattern, sizeof (pattern), "$[(-%s)/(-1)]", *num);
89         int ret = wordexp (pattern, &w, WRDE_NOCMD);
90         if (ret == 0)
91           {
92             /* If the call is successful, the result must match the
93                original number.  */
94             TEST_COMPARE (w.we_wordc, 1);
95             TEST_COMPARE_STRING (w.we_wordv[0], *num);
96             TEST_COMPARE_STRING (w.we_wordv[1], NULL);
97             wordfree (&w);
98           }
99         else
100           /* Otherwise, the test must fail with a syntax error.  */
101           TEST_COMPARE (ret, WRDE_SYNTAX);
102
103         /* In both cases, command execution is not permitted.  */
104         if (pid_tests_supported)
105           TEST_COMPARE (expected_pid++, next_pid ());
106       }
107   }
108
109   /* (Lack of) command execution tests.  */
110
111   expect_failure ("$(ls)", WRDE_CMDSUB);
112
113   /* Test for CVE-2014-7817. We test 3 combinations of command
114      substitution inside an arithmetic expression to make sure that
115      no commands are executed and error is returned.  */
116   expect_failure ("$((`echo 1`))", WRDE_CMDSUB);
117   expect_failure ("$((1+`echo 1`))", WRDE_CMDSUB);
118   expect_failure ("$((1+$((`echo 1`))))", WRDE_CMDSUB);
119
120   expect_failure ("$[1/0]", WRDE_SYNTAX); /* BZ 18100.  */
121 }
122
123 static void
124 subprocess (void *closure)
125 {
126   expected_pid = 2;
127   if (pid_tests_supported)
128     TEST_COMPARE (expected_pid++, next_pid ());
129
130   /* Check that triggering command execution via wordexp results in a
131      PID increase.  */
132   if (pid_tests_supported)
133     {
134       wordexp_t w;
135       TEST_COMPARE (wordexp ("$(echo Test)", &w, 0), 0);
136       TEST_COMPARE (w.we_wordc, 1);
137       TEST_COMPARE_STRING (w.we_wordv[0], "Test");
138       TEST_COMPARE_STRING (w.we_wordv[1], NULL);
139       wordfree (&w);
140
141       pid_t n = next_pid ();
142       printf ("info: self-test resulted in PID %d (processes created: %d)\n",
143               (int) n, (int) (n - expected_pid));
144       TEST_VERIFY (n > expected_pid);
145       expected_pid = n + 1;
146   }
147
148   puts ("info: testing without IFS");
149   unsetenv ("IFS");
150   run_tests ();
151
152   puts ("info: testing with IFS");
153   TEST_COMPARE (setenv ("IFS", " \t\n", 1), 0);
154   run_tests ();
155 }
156
157 static int
158 do_test (void)
159 {
160   support_become_root ();
161
162 #ifdef CLONE_NEWPID
163   if (unshare (CLONE_NEWPID) != 0)
164     printf ("warning: unshare (CLONE_NEWPID) failed: %m\n"
165             "warning: This leads to reduced test coverage.\n");
166   else
167     pid_tests_supported = true;
168 #else
169   printf ("warning: CLONE_NEWPID not available.\n"
170           "warning: This leads to reduced test coverage.\n");
171 #endif
172
173   /* CLONE_NEWPID only has an effect after fork.  */
174   support_isolate_in_subprocess (subprocess, NULL);
175
176   return 0;
177 }
178
179 #include <support/test-driver.c>