1 /* Copyright 2018 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Test util.[ch] module code using gtest.
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13 
14 #include <gtest/gtest.h>
15 
16 #include "bpf.h"
17 #include "util.h"
18 
19 namespace {
20 
dump_env(const char * const * env)21 std::string dump_env(const char *const *env) {
22   std::string result;
23   for (; *env; ++env) {
24     result += *env;
25     result += "\n";
26   }
27 
28   return result;
29 }
30 
31 }  // namespace
32 
33 // Sanity check for the strip func.
TEST(strip,basic)34 TEST(strip, basic) {
35   char str[] = " foo\t";
36   ASSERT_EQ("foo", std::string(strip(str)));
37 }
38 
39 // Make sure we don't crash with various "null"-like inputs.
TEST(tokenize,null_stringp)40 TEST(tokenize, null_stringp) {
41   ASSERT_EQ(nullptr, tokenize(nullptr, nullptr));
42   ASSERT_EQ(nullptr, tokenize(nullptr, ""));
43   ASSERT_EQ(nullptr, tokenize(nullptr, ","));
44 
45   char *p = nullptr;
46   ASSERT_EQ(nullptr, tokenize(&p, nullptr));
47 }
48 
49 // Make sure we don't crash with various "null"-like inputs.
TEST(tokenize,null_delim)50 TEST(tokenize, null_delim) {
51   char str[] = "a,b,c";
52   char *p = str;
53   ASSERT_EQ(str, tokenize(&p, nullptr));
54   ASSERT_EQ(nullptr, p);
55   ASSERT_EQ(str, std::string("a,b,c"));
56 
57   p = str;
58   ASSERT_EQ(str, tokenize(&p, ""));
59   ASSERT_EQ(nullptr, p);
60   ASSERT_EQ(str, std::string("a,b,c"));
61 }
62 
63 // Sanity check for the tokenize func.
TEST(tokenize,basic)64 TEST(tokenize, basic) {
65   char str[] = "a,b,c";
66   char *p = str;
67   ASSERT_EQ("a", std::string(tokenize(&p, ",")));
68   ASSERT_EQ("b", std::string(tokenize(&p, ",")));
69   ASSERT_EQ("c", std::string(tokenize(&p, ",")));
70   ASSERT_EQ(nullptr, p);
71   ASSERT_EQ(nullptr, tokenize(&p, ","));
72 }
73 
74 // Check edge case with an empty string.
TEST(tokenize,empty_string)75 TEST(tokenize, empty_string) {
76   char str[] = "";
77   char *p = str;
78   ASSERT_EQ("", std::string(tokenize(&p, ",")));
79   ASSERT_EQ(nullptr, p);
80   ASSERT_EQ(nullptr, tokenize(&p, ","));
81 }
82 
83 // Check behavior with empty tokens at the start/middle/end.
TEST(tokenize,empty_tokens)84 TEST(tokenize, empty_tokens) {
85   char str[] = ",,a,b,,,c,,";
86   char *p = str;
87   ASSERT_EQ("", std::string(tokenize(&p, ",")));
88   ASSERT_EQ("", std::string(tokenize(&p, ",")));
89   ASSERT_EQ("a", std::string(tokenize(&p, ",")));
90   ASSERT_EQ("b", std::string(tokenize(&p, ",")));
91   ASSERT_EQ("", std::string(tokenize(&p, ",")));
92   ASSERT_EQ("", std::string(tokenize(&p, ",")));
93   ASSERT_EQ("c", std::string(tokenize(&p, ",")));
94   ASSERT_EQ("", std::string(tokenize(&p, ",")));
95   ASSERT_EQ("", std::string(tokenize(&p, ",")));
96   ASSERT_EQ(nullptr, p);
97   ASSERT_EQ(nullptr, tokenize(&p, ","));
98 }
99 
100 // Check environment manipulation functions.
TEST(environment,copy_and_modify)101 TEST(environment, copy_and_modify) {
102   minijail_free_env(nullptr);
103 
104   char **env = minijail_copy_env(nullptr);
105   EXPECT_EQ("", dump_env(env));
106   minijail_free_env(env);
107 
108   const char *const kConstEnv[] = {
109     "val1=1",
110     "val2=2",
111     "dup=1",
112     "dup=2",
113     "empty=",
114     nullptr,
115   };
116 
117   // libc unfortunately uses char* const[] as the type for the environment, and
118   // we match that. It's actually missing a const-ness of the chars making up
119   // the environment strings, but we need that to initialize the |kEnv|
120   // constant. Hence, do a cast here to force things into alignment...
121   char* const* kEnv = const_cast<char* const*>(kConstEnv);
122 
123   env = minijail_copy_env(kEnv);
124   EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
125   minijail_free_env(env);
126 
127   env = minijail_copy_env(kEnv);
128   EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
129 
130   EXPECT_EQ(EINVAL, minijail_setenv(nullptr, "val1", "3", 1));
131   char **env_ret = nullptr;
132   EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "val1", "3", 1));
133 
134   env_ret = env;
135   EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, nullptr, "3", 1));
136   EXPECT_EQ(env, env_ret);
137   EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "", "3", 1));
138   EXPECT_EQ(env, env_ret);
139   EXPECT_EQ(EINVAL, minijail_setenv(&env_ret, "", nullptr, 1));
140   EXPECT_EQ(env, env_ret);
141 
142   EXPECT_EQ(0, minijail_setenv(&env, "val1", "3", 0));
143   EXPECT_EQ("val1=1\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
144   EXPECT_EQ(0, minijail_setenv(&env, "val1", "3", 1));
145   EXPECT_EQ("val1=3\nval2=2\ndup=1\ndup=2\nempty=\n", dump_env(env));
146   EXPECT_EQ(0, minijail_setenv(&env, "val2", "4", 1));
147   EXPECT_EQ("val1=3\nval2=4\ndup=1\ndup=2\nempty=\n", dump_env(env));
148   EXPECT_EQ(0, minijail_setenv(&env, "dup", "5", 1));
149   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\n", dump_env(env));
150   EXPECT_EQ(0, minijail_setenv(&env, "empty", "6", 1));
151   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=6\n", dump_env(env));
152   EXPECT_EQ(0, minijail_setenv(&env, "empty", "", 1));
153   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\n", dump_env(env));
154   EXPECT_EQ(0, minijail_setenv(&env, "new1", "7", 0));
155   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\n", dump_env(env));
156   EXPECT_EQ(0, minijail_setenv(&env, "new2", "8", 1));
157   EXPECT_EQ("val1=3\nval2=4\ndup=5\ndup=2\nempty=\nnew1=7\nnew2=8\n",
158             dump_env(env));
159 
160   minijail_free_env(env);
161 }
162 
TEST(parse_single_constant,formats)163 TEST(parse_single_constant, formats) {
164   char *end;
165   long int c = 0;
166   std::string constant;
167 
168   // Check base 10 works.
169   constant = "1234";
170   c = parse_constant(const_cast<char*>(constant.data()), &end);
171   EXPECT_EQ(1234, c);
172 
173   // Check base 16 works.
174   constant = "0x1234";
175   c = parse_constant(const_cast<char*>(constant.data()), &end);
176   EXPECT_EQ(0x1234, c);
177 
178   // Check base 8 works.
179   constant = "01234";
180   c = parse_constant(const_cast<char*>(constant.data()), &end);
181   EXPECT_EQ(01234, c);
182 }
183 
TEST(parse_constant,unsigned)184 TEST(parse_constant, unsigned) {
185   char *end;
186   long int c = 0;
187   std::string constant;
188 
189 #if defined(BITS32)
190   constant = "0x80000000";
191   c = parse_constant(const_cast<char*>(constant.data()), &end);
192   EXPECT_EQ(0x80000000U, static_cast<unsigned long int>(c));
193 
194 #elif defined(BITS64)
195   constant = "0x8000000000000000";
196   c = parse_constant(const_cast<char*>(constant.data()), &end);
197   EXPECT_EQ(0x8000000000000000UL, static_cast<unsigned long int>(c));
198 
199 #else
200 # error "unknown bits!"
201 #endif
202 }
203 
TEST(parse_constant,unsigned_toobig)204 TEST(parse_constant, unsigned_toobig) {
205   char *end;
206   long int c = 0;
207   std::string constant;
208 
209 #if defined(BITS32)
210   constant = "0x100000000";  // Too big for 32-bit unsigned long int.
211   c = parse_constant(const_cast<char*>(constant.data()), &end);
212   // Error case should return 0.
213   EXPECT_EQ(0, c);
214 
215 #elif defined(BITS64)
216   constant = "0x10000000000000000";
217   c = parse_constant(const_cast<char*>(constant.data()), &end);
218   // Error case should return 0.
219   EXPECT_EQ(0, c);
220 
221 #else
222 # error "unknown bits!"
223 #endif
224 }
225 
TEST(parse_constant,signed)226 TEST(parse_constant, signed) {
227   char *end;
228   long int c = 0;
229   std::string constant = "-1";
230   c = parse_constant(const_cast<char*>(constant.data()), &end);
231   EXPECT_EQ(-1, c);
232 }
233 
TEST(parse_constant,signed_toonegative)234 TEST(parse_constant, signed_toonegative) {
235   char *end;
236   long int c = 0;
237   std::string constant;
238 
239 #if defined(BITS32)
240   constant = "-0x80000001";
241   c = parse_constant(const_cast<char*>(constant.data()), &end);
242   // Error case should return 0.
243   EXPECT_EQ(0, c);
244 
245 #elif defined(BITS64)
246   constant = "-0x8000000000000001";
247   c = parse_constant(const_cast<char*>(constant.data()), &end);
248   // Error case should return 0.
249   EXPECT_EQ(0, c);
250 
251 #else
252 # error "unknown bits!"
253 #endif
254 }
255 
TEST(parse_constant,complements)256 TEST(parse_constant, complements) {
257   char* end;
258   long int c = 0;
259   std::string constant;
260 
261 #if defined(BITS32)
262   constant = "~0x005AF0FF|~0xFFA50FFF";
263   c = parse_constant(const_cast<char*>(constant.data()), &end);
264   EXPECT_EQ(c, 0xFFFFFF00);
265   constant = "0x0F|~(0x005AF000|0x00A50FFF)|0xF0";
266   c = parse_constant(const_cast<char*>(constant.data()), &end);
267   EXPECT_EQ(c, 0xFF0000FF);
268 
269 #elif defined(BITS64)
270   constant = "~0x00005A5AF0F0FFFF|~0xFFFFA5A50F0FFFFF";
271   c = parse_constant(const_cast<char*>(constant.data()), &end);
272   EXPECT_EQ(c, 0xFFFFFFFFFFFF0000UL);
273   constant = "0x00FF|~(0x00005A5AF0F00000|0x0000A5A50F0FFFFF)|0xFF00";
274   c = parse_constant(const_cast<char*>(constant.data()), &end);
275   EXPECT_EQ(c, 0xFFFF00000000FFFFUL);
276 
277 #else
278 # error "unknown bits!"
279 #endif
280 }
281 
TEST(parse_constant,parenthesized_expresions)282 TEST(parse_constant, parenthesized_expresions) {
283   char* end;
284 
285   const std::vector<const char*> bad_expressions = {
286       "(1", "1)", "(1)1", "|(1)", "(1)|", "()",
287       "(",  "((", "(()",  "(()1", "1(0)",
288   };
289   for (const auto* expression : bad_expressions) {
290     std::string mutable_expression = expression;
291     long int c =
292         parse_constant(const_cast<char*>(mutable_expression.data()), &end);
293     EXPECT_EQ(reinterpret_cast<const void*>(end),
294               reinterpret_cast<const void*>(mutable_expression.data()));
295     // Error case should return 0.
296     EXPECT_EQ(c, 0) << "For expression: \"" << expression << "\"";
297   }
298 
299   const std::vector<const char*> good_expressions = {
300       "(3)", "(1)|2", "1|(2)", "(1)|(2)", "((3))", "0|(1|2)", "(0|1|2)",
301   };
302   for (const auto* expression : good_expressions) {
303     std::string mutable_expression = expression;
304     long int c =
305         parse_constant(const_cast<char*>(mutable_expression.data()), &end);
306     EXPECT_EQ(c, 3) << "For expression: \"" << expression << "\"";
307   }
308 }
309 
TEST(parse_size,complete)310 TEST(parse_size, complete) {
311   size_t size;
312 
313   ASSERT_EQ(0, parse_size(&size, "42"));
314   ASSERT_EQ(42U, size);
315 
316   ASSERT_EQ(0, parse_size(&size, "16K"));
317   ASSERT_EQ(16384U, size);
318 
319   ASSERT_EQ(0, parse_size(&size, "1M"));
320   ASSERT_EQ(1024U * 1024, size);
321 
322   uint64_t gigabyte = 1024ULL * 1024 * 1024;
323   ASSERT_EQ(0, parse_size(&size, "3G"));
324   ASSERT_EQ(3U, size / gigabyte);
325   ASSERT_EQ(0U, size % gigabyte);
326 
327   ASSERT_EQ(0, parse_size(&size, "4294967294"));
328   ASSERT_EQ(3U, size / gigabyte);
329   ASSERT_EQ(gigabyte - 2, size % gigabyte);
330 
331 #if __WORDSIZE == 64
332   uint64_t exabyte = gigabyte * 1024 * 1024 * 1024;
333   ASSERT_EQ(0, parse_size(&size, "9E"));
334   ASSERT_EQ(9U, size / exabyte);
335   ASSERT_EQ(0U, size % exabyte);
336 
337   ASSERT_EQ(0, parse_size(&size, "15E"));
338   ASSERT_EQ(15U, size / exabyte);
339   ASSERT_EQ(0U, size % exabyte);
340 
341   ASSERT_EQ(0, parse_size(&size, "18446744073709551614"));
342   ASSERT_EQ(15U, size / exabyte);
343   ASSERT_EQ(exabyte - 2, size % exabyte);
344 
345   ASSERT_EQ(-ERANGE, parse_size(&size, "16E"));
346   ASSERT_EQ(-ERANGE, parse_size(&size, "19E"));
347   ASSERT_EQ(-EINVAL, parse_size(&size, "7GTPE"));
348 #elif __WORDSIZE == 32
349   ASSERT_EQ(-ERANGE, parse_size(&size, "5G"));
350   ASSERT_EQ(-ERANGE, parse_size(&size, "9G"));
351   ASSERT_EQ(-ERANGE, parse_size(&size, "9E"));
352   ASSERT_EQ(-ERANGE, parse_size(&size, "7GTPE"));
353 #endif
354 
355   ASSERT_EQ(-EINVAL, parse_size(&size, ""));
356   ASSERT_EQ(-EINVAL, parse_size(&size, "14u"));
357   ASSERT_EQ(-EINVAL, parse_size(&size, "14.2G"));
358   ASSERT_EQ(-EINVAL, parse_size(&size, "-1G"));
359   ASSERT_EQ(-EINVAL, parse_size(&size, "; /bin/rm -- "));
360 }
361