]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-env-util.c
tree-wide: various ubsan zero size memory fixes
[thirdparty/systemd.git] / src / test / test-env-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
c24eb49e 2
c24eb49e
LP
3#include <string.h>
4
4d1a6904 5#include "env-util.h"
a096d8c8
ZJS
6#include "fd-util.h"
7#include "fileio.h"
07630cea
LP
8#include "string-util.h"
9#include "strv.h"
10#include "util.h"
c24eb49e 11
940bd473
TA
12static void test_strv_env_delete(void) {
13 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
14
15 a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL);
9b5d6bd9
LP
16 assert_se(a);
17
940bd473 18 b = strv_new("PIEP", "FOO", NULL);
9b5d6bd9
LP
19 assert_se(b);
20
940bd473 21 c = strv_new("SCHLUMPF", NULL);
9b5d6bd9 22 assert_se(c);
940bd473
TA
23
24 d = strv_env_delete(a, 2, b, c);
9b5d6bd9 25 assert_se(d);
940bd473 26
9b5d6bd9
LP
27 assert_se(streq(d[0], "WALDO=WALDO"));
28 assert_se(streq(d[1], "WALDO="));
29 assert_se(strv_length(d) == 2);
940bd473
TA
30}
31
6162512c
RS
32static void test_strv_env_get(void) {
33 char **l;
34
35 l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4");
36
37 assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2"));
38 assert_se(streq(strv_env_get(l, "THREE"), "3"));
39 assert_se(streq(strv_env_get(l, "FOUR"), "4"));
40}
41
940bd473
TA
42static void test_strv_env_unset(void) {
43 _cleanup_strv_free_ char **l = NULL;
44
45 l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
9b5d6bd9 46 assert_se(l);
940bd473 47
9b5d6bd9 48 assert_se(strv_env_unset(l, "SCHLUMPF") == l);
940bd473 49
9b5d6bd9
LP
50 assert_se(streq(l[0], "PIEP"));
51 assert_se(streq(l[1], "NANANANA=YES"));
52 assert_se(strv_length(l) == 2);
940bd473
TA
53}
54
55static void test_strv_env_set(void) {
56 _cleanup_strv_free_ char **l = NULL, **r = NULL;
57
58 l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
9b5d6bd9 59 assert_se(l);
940bd473
TA
60
61 r = strv_env_set(l, "WALDO=WALDO");
9b5d6bd9 62 assert_se(r);
940bd473 63
9b5d6bd9
LP
64 assert_se(streq(r[0], "PIEP"));
65 assert_se(streq(r[1], "SCHLUMPF=SMURFF"));
66 assert_se(streq(r[2], "NANANANA=YES"));
67 assert_se(streq(r[3], "WALDO=WALDO"));
68 assert_se(strv_length(r) == 4);
940bd473
TA
69}
70
1f28b2de
TA
71static void test_strv_env_merge(void) {
72 _cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL;
73
74 a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL);
9b5d6bd9
LP
75 assert_se(a);
76
1f28b2de 77 b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
9b5d6bd9 78 assert_se(b);
c24eb49e 79
1f28b2de 80 r = strv_env_merge(2, a, b);
9b5d6bd9
LP
81 assert_se(r);
82 assert_se(streq(r[0], "FOO="));
83 assert_se(streq(r[1], "WALDO="));
84 assert_se(streq(r[2], "PIEP"));
85 assert_se(streq(r[3], "SCHLUMPF=SMURFF"));
86 assert_se(streq(r[4], "PIEP="));
87 assert_se(streq(r[5], "NANANANA=YES"));
88 assert_se(strv_length(r) == 6);
89
90 assert_se(strv_env_clean(r) == r);
91 assert_se(streq(r[0], "FOO="));
92 assert_se(streq(r[1], "WALDO="));
93 assert_se(streq(r[2], "SCHLUMPF=SMURFF"));
94 assert_se(streq(r[3], "PIEP="));
95 assert_se(streq(r[4], "NANANANA=YES"));
96 assert_se(strv_length(r) == 5);
1f28b2de
TA
97}
98
37f3ffca
RS
99static void test_env_strv_get_n(void) {
100 const char *_env[] = {
101 "FOO=NO NO NO",
102 "FOO=BAR BAR",
103 "BAR=waldo",
104 "PATH=unset",
105 NULL
106 };
107 char **env = (char**) _env;
108
109 assert_se(streq(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR"));
110 assert_se(streq(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
111 assert_se(streq(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR"));
112 assert_se(streq(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR"));
113
114 assert_se(streq(strv_env_get_n(env, "PATH__", 4, 0), "unset"));
115 assert_se(streq(strv_env_get_n(env, "PATH", 4, 0), "unset"));
116 assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
117 assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset"));
118
119 env[3] = NULL; /* kill our $PATH */
120
121 assert_se(!strv_env_get_n(env, "PATH__", 4, 0));
122 assert_se(!strv_env_get_n(env, "PATH", 4, 0));
123 assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT),
124 getenv("PATH")));
125 assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT),
126 getenv("PATH")));
127}
128
ccad1fd0
ZJS
129static void test_replace_env(bool braceless) {
130 const char *env[] = {
131 "FOO=BAR BAR",
132 "BAR=waldo",
133 NULL
134 };
135 _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL;
136 unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless;
137
138 t = replace_env("FOO=$FOO=${FOO}", (char**) env, flags);
139 assert_se(streq(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR"));
140
141 s = replace_env("BAR=$BAR=${BAR}", (char**) env, flags);
142 assert_se(streq(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo"));
143
144 q = replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags);
145 assert_se(streq(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR="));
146
a93236aa
ZJS
147 r = replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags);
148 assert_se(streq(r, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo"));
ccad1fd0
ZJS
149
150 p = replace_env("${BAR}$BAR$BAR", (char**) env, flags);
151 assert_se(streq(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR"));
152}
153
f50ce8fc
ZJS
154static void test_replace_env2(bool extended) {
155 const char *env[] = {
156 "FOO=foo",
157 "BAR=bar",
158 NULL
159 };
160 _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL, *x = NULL;
161 unsigned flags = REPLACE_ENV_ALLOW_EXTENDED*extended;
162
163 t = replace_env("FOO=${FOO:-${BAR}}", (char**) env, flags);
164 assert_se(streq(t, extended ? "FOO=foo" : "FOO=${FOO:-bar}"));
165
166 s = replace_env("BAR=${XXX:-${BAR}}", (char**) env, flags);
167 assert_se(streq(s, extended ? "BAR=bar" : "BAR=${XXX:-bar}"));
168
169 q = replace_env("XXX=${XXX:+${BAR}}", (char**) env, flags);
170 assert_se(streq(q, extended ? "XXX=" : "XXX=${XXX:+bar}"));
171
172 r = replace_env("FOO=${FOO:+${BAR}}", (char**) env, flags);
173 assert_se(streq(r, extended ? "FOO=bar" : "FOO=${FOO:+bar}"));
174
175 p = replace_env("FOO=${FOO:-${BAR}post}", (char**) env, flags);
176 assert_se(streq(p, extended ? "FOO=foo" : "FOO=${FOO:-barpost}"));
177
178 x = replace_env("XXX=${XXX:+${BAR}post}", (char**) env, flags);
179 assert_se(streq(x, extended ? "XXX=" : "XXX=${XXX:+barpost}"));
180}
181
ccad1fd0 182static void test_replace_env_argv(void) {
c24eb49e
LP
183 const char *env[] = {
184 "FOO=BAR BAR",
185 "BAR=waldo",
186 NULL
187 };
c24eb49e
LP
188 const char *line[] = {
189 "FOO$FOO",
190 "FOO$FOOFOO",
191 "FOO${FOO}$FOO",
192 "FOO${FOO}",
193 "${FOO}",
194 "$FOO",
195 "$FOO$FOO",
196 "${FOO}${BAR}",
197 "${FOO",
df553b58
MS
198 "FOO$$${FOO}",
199 "$$FOO${FOO}",
b82f58bf
RS
200 "${FOO:-${BAR}}",
201 "${QUUX:-${FOO}}",
202 "${FOO:+${BAR}}",
203 "${QUUX:+${BAR}}",
204 "${FOO:+|${BAR}|}}",
205 "${FOO:+|${BAR}{|}",
c24eb49e
LP
206 NULL
207 };
1f28b2de 208 _cleanup_strv_free_ char **r = NULL;
c24eb49e
LP
209
210 r = replace_env_argv((char**) line, (char**) env);
9b5d6bd9
LP
211 assert_se(r);
212 assert_se(streq(r[0], "FOO$FOO"));
213 assert_se(streq(r[1], "FOO$FOOFOO"));
214 assert_se(streq(r[2], "FOOBAR BAR$FOO"));
215 assert_se(streq(r[3], "FOOBAR BAR"));
216 assert_se(streq(r[4], "BAR BAR"));
217 assert_se(streq(r[5], "BAR"));
218 assert_se(streq(r[6], "BAR"));
219 assert_se(streq(r[7], "BAR BARwaldo"));
220 assert_se(streq(r[8], "${FOO"));
df553b58
MS
221 assert_se(streq(r[9], "FOO$BAR BAR"));
222 assert_se(streq(r[10], "$FOOBAR BAR"));
b82f58bf
RS
223 assert_se(streq(r[11], "${FOO:-waldo}"));
224 assert_se(streq(r[12], "${QUUX:-BAR BAR}"));
225 assert_se(streq(r[13], "${FOO:+waldo}"));
226 assert_se(streq(r[14], "${QUUX:+waldo}"));
227 assert_se(streq(r[15], "${FOO:+|waldo|}}"));
228 assert_se(streq(r[16], "${FOO:+|waldo{|}"));
229 assert_se(strv_length(r) == 17);
1f28b2de 230}
a6ff950e 231
4d1a6904 232static void test_env_clean(void) {
4d1a6904
LP
233 _cleanup_strv_free_ char **e;
234
235 e = strv_new("FOOBAR=WALDO",
236 "FOOBAR=WALDO",
237 "FOOBAR",
238 "F",
239 "X=",
240 "F=F",
241 "=",
242 "=F",
243 "",
244 "0000=000",
245 "äöüß=abcd",
246 "abcd=äöüß",
247 "xyz\n=xyz",
248 "xyz=xyz\n",
249 "another=one",
250 "another=final one",
251 NULL);
9b5d6bd9
LP
252 assert_se(e);
253 assert_se(!strv_env_is_valid(e));
254 assert_se(strv_env_clean(e) == e);
255 assert_se(strv_env_is_valid(e));
4d1a6904
LP
256
257 assert_se(streq(e[0], "FOOBAR=WALDO"));
258 assert_se(streq(e[1], "X="));
259 assert_se(streq(e[2], "F=F"));
260 assert_se(streq(e[3], "abcd=äöüß"));
b4346b9a
FB
261 assert_se(streq(e[4], "xyz=xyz\n"));
262 assert_se(streq(e[5], "another=final one"));
263 assert_se(e[6] == NULL);
4d1a6904
LP
264}
265
8354c34e
TA
266static void test_env_name_is_valid(void) {
267 assert_se(env_name_is_valid("test"));
268
269 assert_se(!env_name_is_valid(NULL));
270 assert_se(!env_name_is_valid(""));
b8c83cfc
ZJS
271 assert_se(!env_name_is_valid("xxx\a"));
272 assert_se(!env_name_is_valid("xxx\007b"));
273 assert_se(!env_name_is_valid("\007\009"));
8354c34e
TA
274 assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong"));
275 assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
276}
277
b8c83cfc
ZJS
278static void test_env_value_is_valid(void) {
279 assert_se(env_value_is_valid(""));
280 assert_se(env_value_is_valid("głąb kapuściany"));
281 assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
b4346b9a
FB
282 assert_se(env_value_is_valid("tab\tcharacter"));
283 assert_se(env_value_is_valid("new\nline"));
b8c83cfc
ZJS
284}
285
286static void test_env_assignment_is_valid(void) {
287 assert_se(env_assignment_is_valid("a="));
288 assert_se(env_assignment_is_valid("b=głąb kapuściany"));
289 assert_se(env_assignment_is_valid("c=\\007\\009\\011"));
290 assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
b4346b9a
FB
291 assert_se(env_assignment_is_valid("f=tab\tcharacter"));
292 assert_se(env_assignment_is_valid("g=new\nline"));
b8c83cfc
ZJS
293
294 assert_se(!env_assignment_is_valid("="));
295 assert_se(!env_assignment_is_valid("a b="));
296 assert_se(!env_assignment_is_valid("a ="));
297 assert_se(!env_assignment_is_valid(" b="));
298 /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */
299 assert_se(!env_assignment_is_valid("a.b="));
300 assert_se(!env_assignment_is_valid("a-b="));
301 assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
302 assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
303 assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
304}
305
16eefcaf
RC
306static void test_deserialize_environment(void) {
307 _cleanup_strv_free_ char **env = strv_new("A=1", NULL);
308
16eefcaf 309 assert_se(deserialize_environment(&env, "env=B=2") >= 0);
ea43bdd1 310 assert_se(deserialize_environment(&env, "env=FOO%%=a\\177b\\nc\\td e") >= 0);
16eefcaf 311
ea43bdd1 312 assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e")));
c7d797bb
LR
313
314 assert_se(deserialize_environment(&env, "env=foo\\") < 0);
315 assert_se(deserialize_environment(&env, "env=bar\\_baz") < 0);
16eefcaf
RC
316}
317
a096d8c8
ZJS
318static void test_serialize_environment(void) {
319 char fn[] = "/tmp/test-env-util.XXXXXXX";
320 int fd, r;
321 _cleanup_fclose_ FILE *f = NULL;
322
323 _cleanup_strv_free_ char **env = strv_new("A=1",
324 "B=2",
325 "C=ąęółń",
326 "D=D=a\\x0Ab",
ea43bdd1 327 "FOO%%=a\177b\nc\td e",
a096d8c8
ZJS
328 NULL);
329 _cleanup_strv_free_ char **env2 = NULL;
330
331 fd = mkostemp_safe(fn);
332 assert_se(fd >= 0);
333
334 assert_se(f = fdopen(fd, "r+"));
335
336 assert_se(serialize_environment(f, env) == 0);
337 assert_se(fflush_and_check(f) == 0);
338
339 rewind(f);
340
341 for (;;) {
342 char line[LINE_MAX];
343 const char *l;
344
345 if (!fgets(line, sizeof line, f))
346 break;
347
348 char_array_0(line);
349 l = strstrip(line);
350
351 r = deserialize_environment(&env2, l);
352 assert_se(r == 1);
353 }
354 assert_se(feof(f));
355
356 assert_se(strv_equal(env, env2));
357
358 unlink(fn);
359}
360
1f28b2de 361int main(int argc, char *argv[]) {
940bd473 362 test_strv_env_delete();
6162512c 363 test_strv_env_get();
940bd473
TA
364 test_strv_env_unset();
365 test_strv_env_set();
1f28b2de 366 test_strv_env_merge();
37f3ffca 367 test_env_strv_get_n();
ccad1fd0
ZJS
368 test_replace_env(false);
369 test_replace_env(true);
f50ce8fc
ZJS
370 test_replace_env2(false);
371 test_replace_env2(true);
ccad1fd0 372 test_replace_env_argv();
4d1a6904 373 test_env_clean();
8354c34e 374 test_env_name_is_valid();
b8c83cfc
ZJS
375 test_env_value_is_valid();
376 test_env_assignment_is_valid();
16eefcaf 377 test_deserialize_environment();
a096d8c8 378 test_serialize_environment();
a6ff950e 379
5f7c426e 380 return 0;
c24eb49e 381}