Avoid outputting to TTY after an expected memory corruption in testcase
[platform/upstream/glibc.git] / test-skeleton.c
1 /* Skeleton for test programs.
2    Copyright (C) 1998-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <getopt.h>
24 #include <malloc.h>
25 #include <paths.h>
26 #include <search.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/resource.h>
33 #include <sys/wait.h>
34 #include <sys/param.h>
35 #include <time.h>
36
37 /* The test function is normally called `do_test' and it is called
38    with argc and argv as the arguments.  We nevertheless provide the
39    possibility to overwrite this name.  */
40 #ifndef TEST_FUNCTION
41 # define TEST_FUNCTION do_test (argc, argv)
42 #endif
43
44 #ifndef TEST_DATA_LIMIT
45 # define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with.  */
46 #endif
47
48 #ifndef TIMEOUT
49   /* Default timeout is two seconds.  */
50 # define TIMEOUT 2
51 #endif
52
53 #define OPT_DIRECT 1000
54 #define OPT_TESTDIR 1001
55
56 static struct option options[] =
57 {
58 #ifdef CMDLINE_OPTIONS
59   CMDLINE_OPTIONS
60 #endif
61   { "direct", no_argument, NULL, OPT_DIRECT },
62   { "test-dir", required_argument, NULL, OPT_TESTDIR },
63   { NULL, 0, NULL, 0 }
64 };
65
66 /* PID of the test itself.  */
67 static pid_t pid;
68
69 /* Directory to place temporary files in.  */
70 static const char *test_dir;
71
72 /* List of temporary files.  */
73 struct temp_name_list
74 {
75   struct qelem q;
76   char *name;
77 } *temp_name_list;
78
79 /* Add temporary files in list.  */
80 static void
81 __attribute__ ((unused))
82 add_temp_file (const char *name)
83 {
84   struct temp_name_list *newp
85     = (struct temp_name_list *) calloc (sizeof (*newp), 1);
86   char *newname = strdup (name);
87   if (newp != NULL && newname != NULL)
88     {
89       newp->name = newname;
90       if (temp_name_list == NULL)
91         temp_name_list = (struct temp_name_list *) &newp->q;
92       else
93         insque (newp, temp_name_list);
94     }
95   else
96     free (newp);
97 }
98
99 /* Delete all temporary files.  */
100 static void
101 delete_temp_files (void)
102 {
103   while (temp_name_list != NULL)
104     {
105       remove (temp_name_list->name);
106       free (temp_name_list->name);
107
108       struct temp_name_list *next
109         = (struct temp_name_list *) temp_name_list->q.q_forw;
110       free (temp_name_list);
111       temp_name_list = next;
112     }
113 }
114
115 /* Create a temporary file.  Return the opened file descriptor on
116    success, or -1 on failure.  Write the file name to *FILENAME if
117    FILENAME is not NULL.  In this case, the caller is expected to free
118    *FILENAME.  */
119 static int
120 __attribute__ ((unused))
121 create_temp_file (const char *base, char **filename)
122 {
123   char *fname;
124   int fd;
125
126   fname = (char *) malloc (strlen (test_dir) + 1 + strlen (base)
127                            + sizeof ("XXXXXX"));
128   if (fname == NULL)
129     {
130       puts ("out of memory");
131       return -1;
132     }
133   strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
134
135   fd = mkstemp (fname);
136   if (fd == -1)
137     {
138       printf ("cannot open temporary file '%s': %m\n", fname);
139       free (fname);
140       return -1;
141     }
142
143   add_temp_file (fname);
144   if (filename != NULL)
145     *filename = fname;
146   else
147     free (fname);
148
149   return fd;
150 }
151
152 /* Timeout handler.  We kill the child and exit with an error.  */
153 static void
154 __attribute__ ((noreturn))
155 signal_handler (int sig __attribute__ ((unused)))
156 {
157   int killed;
158   int status;
159
160   assert (pid > 1);
161   /* Kill the whole process group.  */
162   kill (-pid, SIGKILL);
163   /* In case setpgid failed in the child, kill it individually too.  */
164   kill (pid, SIGKILL);
165
166   /* Wait for it to terminate.  */
167   int i;
168   for (i = 0; i < 5; ++i)
169     {
170       killed = waitpid (pid, &status, WNOHANG|WUNTRACED);
171       if (killed != 0)
172         break;
173
174       /* Delay, give the system time to process the kill.  If the
175          nanosleep() call return prematurely, all the better.  We
176          won't restart it since this probably means the child process
177          finally died.  */
178       struct timespec ts;
179       ts.tv_sec = 0;
180       ts.tv_nsec = 100000000;
181       nanosleep (&ts, NULL);
182     }
183   if (killed != 0 && killed != pid)
184     {
185       printf ("Failed to kill test process: %m\n");
186       exit (1);
187     }
188
189 #ifdef CLEANUP_HANDLER
190   CLEANUP_HANDLER;
191 #endif
192
193   if (sig == SIGINT)
194     {
195       signal (sig, SIG_DFL);
196       raise (sig);
197     }
198
199   /* If we expected this signal: good!  */
200 #ifdef EXPECTED_SIGNAL
201   if (EXPECTED_SIGNAL == SIGALRM)
202     exit (0);
203 #endif
204
205   if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL))
206     puts ("Timed out: killed the child process");
207   else if (WIFSTOPPED (status))
208     printf ("Timed out: the child process was %s\n",
209             strsignal (WSTOPSIG (status)));
210   else if (WIFSIGNALED (status))
211     printf ("Timed out: the child process got signal %s\n",
212             strsignal (WTERMSIG (status)));
213   else
214     printf ("Timed out: killed the child process but it exited %d\n",
215             WEXITSTATUS (status));
216
217   /* Exit with an error.  */
218   exit (1);
219 }
220
221 /* Avoid all the buffer overflow messages on stderr.  */
222 static void
223 __attribute__ ((unused))
224 ignore_stderr (void)
225 {
226   int fd = open (_PATH_DEVNULL, O_WRONLY);
227   if (fd == -1)
228     close (STDERR_FILENO);
229   else
230     {
231       dup2 (fd, STDERR_FILENO);
232       close (fd);
233     }
234   setenv ("LIBC_FATAL_STDERR_", "1", 1);
235 }
236
237 /* Set fortification error handler.  Used when tests want to verify that bad
238    code is caught by the library.  */
239 static void
240 __attribute__ ((unused))
241 set_fortify_handler (void (*handler) (int sig))
242 {
243   struct sigaction sa;
244
245   sa.sa_handler = handler;
246   sa.sa_flags = 0;
247   sigemptyset (&sa.sa_mask);
248
249   sigaction (SIGABRT, &sa, NULL);
250   ignore_stderr ();
251 }
252
253 /* We provide the entry point here.  */
254 int
255 main (int argc, char *argv[])
256 {
257   int direct = 0;       /* Directly call the test function?  */
258   int status;
259   int opt;
260   unsigned int timeoutfactor = 1;
261   pid_t termpid;
262
263   /* Make uses of freed and uninitialized memory known.  */
264   mallopt (M_PERTURB, 42);
265
266 #ifdef STDOUT_UNBUFFERED
267   setbuf (stdout, NULL);
268 #endif
269
270   while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1)
271     switch (opt)
272       {
273       case '?':
274         exit (1);
275       case OPT_DIRECT:
276         direct = 1;
277         break;
278       case OPT_TESTDIR:
279         test_dir = optarg;
280         break;
281 #ifdef CMDLINE_PROCESS
282         CMDLINE_PROCESS
283 #endif
284       }
285
286   /* If set, read the test TIMEOUTFACTOR value from the environment.
287      This value is used to scale the default test timeout values. */
288   char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR");
289   if (envstr_timeoutfactor != NULL)
290     {
291       char *envstr_conv = envstr_timeoutfactor;
292       unsigned long int env_fact;
293
294       env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0);
295       if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor)
296         timeoutfactor = MAX (env_fact, 1);
297     }
298
299   /* Set TMPDIR to specified test directory.  */
300   if (test_dir != NULL)
301     {
302       setenv ("TMPDIR", test_dir, 1);
303
304       if (chdir (test_dir) < 0)
305         {
306           printf ("chdir: %m\n");
307           exit (1);
308         }
309     }
310   else
311     {
312       test_dir = getenv ("TMPDIR");
313       if (test_dir == NULL || test_dir[0] == '\0')
314         test_dir = "/tmp";
315     }
316
317   /* Make sure we see all message, even those on stdout.  */
318   setvbuf (stdout, NULL, _IONBF, 0);
319
320   /* Make sure temporary files are deleted.  */
321   atexit (delete_temp_files);
322
323   /* Correct for the possible parameters.  */
324   argv[optind - 1] = argv[0];
325   argv += optind - 1;
326   argc -= optind - 1;
327
328   /* Call the initializing function, if one is available.  */
329 #ifdef PREPARE
330   PREPARE (argc, argv);
331 #endif
332
333   const char *envstr_direct = getenv ("TEST_DIRECT");
334   if (envstr_direct != NULL)
335     {
336       FILE *f = fopen (envstr_direct, "w");
337       if (f == NULL)
338         {
339           printf ("cannot open TEST_DIRECT output file '%s': %m\n",
340                   envstr_direct);
341           exit (1);
342         }
343
344       fprintf (f, "timeout=%u\ntimeoutfactor=%u\n", TIMEOUT, timeoutfactor);
345 #ifdef EXPECTED_STATUS
346       fprintf (f, "exit=%u\n", EXPECTED_STATUS);
347 #endif
348 #ifdef EXPECTED_SIGNAL
349       switch (EXPECTED_SIGNAL)
350         {
351         default: abort ();
352 # define init_sig(signo, name, text) \
353         case signo: fprintf (f, "signal=%s\n", name); break;
354 # include <siglist.h>
355 # undef init_sig
356         }
357 #endif
358
359       if (temp_name_list != NULL)
360         {
361           struct temp_name_list *n;
362           fprintf (f, "temp_files=(\n");
363           for (n = temp_name_list;
364                n != NULL;
365                n = (struct temp_name_list *) n->q.q_forw)
366             fprintf (f, "  '%s'\n", n->name);
367           fprintf (f, ")\n");
368         }
369
370       fclose (f);
371       direct = 1;
372     }
373
374   /* If we are not expected to fork run the function immediately.  */
375   if (direct)
376     return TEST_FUNCTION;
377
378   /* Set up the test environment:
379      - prevent core dumps
380      - set up the timer
381      - fork and execute the function.  */
382
383   pid = fork ();
384   if (pid == 0)
385     {
386       /* This is the child.  */
387 #ifdef RLIMIT_CORE
388       /* Try to avoid dumping core.  */
389       struct rlimit core_limit;
390       core_limit.rlim_cur = 0;
391       core_limit.rlim_max = 0;
392       setrlimit (RLIMIT_CORE, &core_limit);
393 #endif
394
395 #ifdef RLIMIT_DATA
396       /* Try to avoid eating all memory if a test leaks.  */
397       struct rlimit data_limit;
398       if (getrlimit (RLIMIT_DATA, &data_limit) == 0)
399         {
400           if (TEST_DATA_LIMIT == RLIM_INFINITY)
401             data_limit.rlim_cur = data_limit.rlim_max;
402           else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT)
403             data_limit.rlim_cur = MIN ((rlim_t) TEST_DATA_LIMIT,
404                                        data_limit.rlim_max);
405           if (setrlimit (RLIMIT_DATA, &data_limit) < 0)
406             printf ("setrlimit: RLIMIT_DATA: %m\n");
407         }
408       else
409         printf ("getrlimit: RLIMIT_DATA: %m\n");
410 #endif
411
412       /* We put the test process in its own pgrp so that if it bogusly
413          generates any job control signals, they won't hit the whole build.  */
414       if (setpgid (0, 0) != 0)
415         printf ("Failed to set the process group ID: %m\n");
416
417       /* Execute the test function and exit with the return value.   */
418       exit (TEST_FUNCTION);
419     }
420   else if (pid < 0)
421     {
422       printf ("Cannot fork test program: %m\n");
423       exit (1);
424     }
425
426   /* Set timeout.  */
427   signal (SIGALRM, signal_handler);
428   alarm (TIMEOUT * timeoutfactor);
429
430   /* Make sure we clean up if the wrapper gets interrupted.  */
431   signal (SIGINT, signal_handler);
432
433   /* Wait for the regular termination.  */
434   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
435   if (termpid == -1)
436     {
437       printf ("Waiting for test program failed: %m\n");
438       exit (1);
439     }
440   if (termpid != pid)
441     {
442       printf ("Oops, wrong test program terminated: expected %ld, got %ld\n",
443               (long int) pid, (long int) termpid);
444       exit (1);
445     }
446
447   /* Process terminated normaly without timeout etc.  */
448   if (WIFEXITED (status))
449     {
450 #ifndef EXPECTED_STATUS
451 # ifndef EXPECTED_SIGNAL
452       /* Simply exit with the return value of the test.  */
453       return WEXITSTATUS (status);
454 # else
455       printf ("Expected signal '%s' from child, got none\n",
456               strsignal (EXPECTED_SIGNAL));
457       exit (1);
458 # endif
459 #else
460       if (WEXITSTATUS (status) != EXPECTED_STATUS)
461         {
462           printf ("Expected status %d, got %d\n",
463                   EXPECTED_STATUS, WEXITSTATUS (status));
464           exit (1);
465         }
466
467       return 0;
468 #endif
469     }
470   /* Process was killed by timer or other signal.  */
471   else
472     {
473 #ifndef EXPECTED_SIGNAL
474       printf ("Didn't expect signal from child: got `%s'\n",
475               strsignal (WTERMSIG (status)));
476       exit (1);
477 #else
478       if (WTERMSIG (status) != EXPECTED_SIGNAL)
479         {
480           printf ("Incorrect signal from child: got `%s', need `%s'\n",
481                   strsignal (WTERMSIG (status)),
482                   strsignal (EXPECTED_SIGNAL));
483           exit (1);
484         }
485
486       return 0;
487 #endif
488     }
489 }