Branch data Line data Source code
1 : : #include "sute.h"
2 : : #include <stdlib.h>
3 : : #include <string.h>
4 : :
5 : : /**
6 : : * @brief Save the current TMPDIR value and clear the output pointer when unset
7 : : *
8 : : * @param[out] saved_tmpdir_out Heap-allocated TMPDIR copy or NULL when unset
9 : : * @return Return status code
10 : : */
11 : 2 : static Return save_tmpdir_value(char **saved_tmpdir_out)
12 : : {
13 : : /* Status returned by this function through provide()
14 : : Default value assumes successful completion */
15 : 2 : Return status = SUCCESS;
16 : 2 : const char *original_tmpdir = NULL;
17 : :
18 [ - + ]: 2 : if(saved_tmpdir_out == NULL)
19 : : {
20 : 0 : status = FAILURE;
21 : : }
22 : :
23 [ + - ]: 2 : if(SUCCESS == status)
24 : : {
25 : 2 : *saved_tmpdir_out = NULL;
26 : 2 : original_tmpdir = getenv("TMPDIR");
27 : :
28 : 2 : IF(original_tmpdir != NULL)
29 : : {
30 : 2 : *saved_tmpdir_out = strdup(original_tmpdir);
31 : :
32 [ - + ]: 2 : if(*saved_tmpdir_out == NULL)
33 : : {
34 : 0 : status = FAILURE;
35 : : }
36 : : }
37 : : }
38 : :
39 : 2 : deliver(status);
40 : : }
41 : :
42 : : /**
43 : : * @brief Restore TMPDIR to a previously saved value or unset it when NULL
44 : : *
45 : : * @param[in] saved_tmpdir Saved TMPDIR value or NULL when TMPDIR was unset
46 : : * @return Return status code
47 : : */
48 : 2 : static Return restore_tmpdir_value(const char *saved_tmpdir)
49 : : {
50 : 2 : int restore_tmpdir_status = 0;
51 : :
52 : 2 : IF(saved_tmpdir != NULL)
53 : : {
54 : 2 : restore_tmpdir_status = setenv("TMPDIR",saved_tmpdir,1);
55 : : } else {
56 : 0 : restore_tmpdir_status = unsetenv("TMPDIR");
57 : : }
58 : :
59 [ + - ]: 2 : return(restore_tmpdir_status == 0 ? SUCCESS : FAILURE);
60 : : }
61 : :
62 : : /**
63 : : *
64 : : * @brief create_directory() should accept a symlinked directory component in TMPDIR
65 : : *
66 : : */
67 : 1 : static Return test0004_1(void)
68 : : {
69 : 1 : INITTEST;
70 : :
71 : 1 : char *saved_tmpdir = NULL;
72 : 1 : bool file_exists = false;
73 : 1 : m_create(char,symlinked_tmpdir,MEMORY_STRING);
74 : 1 : m_create(char,expected_directory_path,MEMORY_STRING);
75 : 1 : Return restore_status = SUCCESS;
76 : 1 : Return cleanup_status = SUCCESS;
77 : :
78 : 1 : ASSERT(SUCCESS == save_tmpdir_value(&saved_tmpdir));
79 : 1 : ASSERT(SUCCESS == create_directory("0004_symlink_parent"));
80 : 1 : ASSERT(SUCCESS == create_directory("0004_symlink_parent/real_tmp_root"));
81 : 1 : ASSERT(SUCCESS == create_symlink("real_tmp_root","0004_symlink_parent/link_tmp_root"));
82 : 1 : ASSERT(SUCCESS == construct_path("0004_symlink_parent/link_tmp_root",symlinked_tmpdir));
83 : 1 : ASSERT(SUCCESS == set_environment_variable("TMPDIR",m_text(symlinked_tmpdir)));
84 : 1 : ASSERT(SUCCESS == create_directory("a/b"));
85 : :
86 : 1 : restore_status = restore_tmpdir_value(saved_tmpdir);
87 : :
88 [ + - ]: 1 : if(SUCCESS == restore_status)
89 : : {
90 [ + - ]: 1 : if(SUCCESS == construct_path("0004_symlink_parent/real_tmp_root/a/b",expected_directory_path)
91 [ + - ]: 1 : && SUCCESS == check_file_exists(&file_exists,m_text(expected_directory_path)))
92 : : {
93 [ - + ]: 1 : if(file_exists != true)
94 : : {
95 [ # # ]: 0 : if(SUCCESS == status)
96 : : {
97 : 0 : status = FAILURE;
98 : : }
99 : : }
100 [ # # ]: 0 : } else if(SUCCESS == status){
101 : 0 : status = FAILURE;
102 : : }
103 : :
104 : 1 : cleanup_status = delete_path("0004_symlink_parent");
105 : : }
106 : :
107 [ + - ]: 1 : if(SUCCESS == status)
108 : : {
109 : 1 : ASSERT(SUCCESS == restore_status);
110 : 1 : ASSERT(SUCCESS == cleanup_status);
111 : : }
112 : :
113 : 1 : free(saved_tmpdir);
114 : 1 : call(m_del(expected_directory_path));
115 : 1 : call(m_del(symlinked_tmpdir));
116 : :
117 : 1 : RETURN_STATUS;
118 : : }
119 : :
120 : : /**
121 : : *
122 : : * @brief create_directory() should reject a TMPDIR component that resolves to a file
123 : : *
124 : : */
125 : 1 : static Return test0004_2(void)
126 : : {
127 : 1 : INITTEST;
128 : :
129 : 1 : char *saved_tmpdir = NULL;
130 : 1 : m_create(char,symlinked_tmpdir,MEMORY_STRING);
131 : 1 : Return restore_status = SUCCESS;
132 : 1 : Return cleanup_status = SUCCESS;
133 : :
134 : 1 : ASSERT(SUCCESS == save_tmpdir_value(&saved_tmpdir));
135 : 1 : ASSERT(SUCCESS == create_directory("0004_symlink_bad_parent"));
136 : 1 : ASSERT(SUCCESS == truncate_file_to_zero_size("0004_symlink_bad_parent/file_target"));
137 : 1 : ASSERT(SUCCESS == create_symlink("file_target","0004_symlink_bad_parent/link_file_root"));
138 : 1 : ASSERT(SUCCESS == construct_path("0004_symlink_bad_parent/link_file_root",symlinked_tmpdir));
139 : 1 : ASSERT(SUCCESS == set_environment_variable("TMPDIR",m_text(symlinked_tmpdir)));
140 : 1 : ASSERT(FAILURE == create_directory("a/b"));
141 : :
142 : 1 : restore_status = restore_tmpdir_value(saved_tmpdir);
143 : :
144 [ + - ]: 1 : if(SUCCESS == restore_status)
145 : : {
146 : 1 : cleanup_status = delete_path("0004_symlink_bad_parent");
147 : : }
148 : :
149 [ + - ]: 1 : if(SUCCESS == status)
150 : : {
151 : 1 : ASSERT(SUCCESS == restore_status);
152 : 1 : ASSERT(SUCCESS == cleanup_status);
153 : : }
154 : :
155 : 1 : free(saved_tmpdir);
156 : 1 : call(m_del(symlinked_tmpdir));
157 : :
158 : 1 : RETURN_STATUS;
159 : : }
160 : :
161 : : /**
162 : : * @brief Run create_directory() unit tests
163 : : */
164 : 1 : Return test0004(void)
165 : : {
166 : 1 : INITTEST;
167 : :
168 : 1 : TEST(test0004_1,"create_directory() accepts a symlinked directory in TMPDIR");
169 : 1 : TEST(test0004_2,"create_directory() rejects a symlinked file in TMPDIR");
170 : :
171 : 1 : RETURN_STATUS;
172 : : }
|