]>
Commit | Line | Data |
---|---|---|
961d7cff AZ |
1 | /* Check if realpath does not consume extra stack space based on symlink |
2 | existance in the path (BZ #26341) | |
3 | Copyright (C) 2021 Free Software Foundation, Inc. | |
4 | This file is part of the GNU C Library. | |
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 | <https://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <sys/param.h> | |
23 | #include <unistd.h> | |
24 | ||
25 | #define __sysconf sysconf | |
26 | #include <eloop-threshold.h> | |
27 | #include <support/check.h> | |
28 | #include <support/support.h> | |
29 | #include <support/temp_file.h> | |
30 | #include <support/xunistd.h> | |
31 | #include <support/xthread.h> | |
32 | ||
33 | static char *filename; | |
34 | static size_t filenamelen; | |
35 | static char *linkname; | |
36 | ||
37 | #ifndef PATH_MAX | |
38 | # define PATH_MAX 1024 | |
39 | #endif | |
40 | ||
41 | static void | |
42 | create_link (void) | |
43 | { | |
44 | int fd = create_temp_file ("tst-canon-bz26341", &filename); | |
45 | TEST_VERIFY_EXIT (fd != -1); | |
46 | xclose (fd); | |
47 | ||
48 | /* Create MAXLINKS symbolic links to the temporary filename. | |
49 | On exit, linkname has the last link created. */ | |
50 | char *prevlink = filename; | |
51 | int maxlinks = __eloop_threshold (); | |
52 | for (int i = 0; i < maxlinks; i++) | |
53 | { | |
54 | linkname = xasprintf ("%s%d", filename, i); | |
55 | xsymlink (prevlink, linkname); | |
56 | add_temp_file (linkname); | |
57 | prevlink = linkname; | |
58 | } | |
59 | ||
60 | filenamelen = strlen (filename); | |
61 | } | |
62 | ||
63 | static void * | |
64 | do_realpath (void *arg) | |
65 | { | |
66 | /* Old implementation of realpath allocates a PATH_MAX using alloca | |
67 | for each symlink in the path, leading to MAXSYMLINKS times PATH_MAX | |
68 | maximum stack usage. | |
69 | This stack allocations tries fill the thread allocated stack minus | |
4631c237 ST |
70 | the resolved path (plus some slack), the realpath (plus some |
71 | slack), and the system call usage (plus some slack). | |
961d7cff AZ |
72 | If realpath uses more than 2 * PATH_MAX plus some slack it will trigger |
73 | a stackoverflow. */ | |
74 | ||
4631c237 | 75 | const size_t syscall_usage = 1 * PATH_MAX + 1024; |
961d7cff AZ |
76 | const size_t realpath_usage = 2 * PATH_MAX + 1024; |
77 | const size_t thread_usage = 1 * PATH_MAX + 1024; | |
78 | size_t stack_size = support_small_thread_stack_size () | |
4631c237 | 79 | - syscall_usage - realpath_usage - thread_usage; |
961d7cff AZ |
80 | char stack[stack_size]; |
81 | char *resolved = stack + stack_size - thread_usage + 1024; | |
82 | ||
83 | char *p = realpath (linkname, resolved); | |
84 | TEST_VERIFY (p != NULL); | |
85 | TEST_COMPARE_BLOB (resolved, filenamelen, filename, filenamelen); | |
86 | ||
87 | return NULL; | |
88 | } | |
89 | ||
90 | static int | |
91 | do_test (void) | |
92 | { | |
93 | create_link (); | |
94 | ||
95 | pthread_t th = xpthread_create (support_small_stack_thread_attribute (), | |
96 | do_realpath, NULL); | |
97 | xpthread_join (th); | |
98 | ||
99 | return 0; | |
100 | } | |
101 | ||
102 | #include <support/test-driver.c> |