The <inlineopt> test discovered the issue
fixed by commit "buffer: Fix buf_parse eating input".
Change-Id: Icb91d9c560b6f78f16571ac3052cc566d94afe99
Signed-off-by: Frank Lichtenheld <frank@lichtenheld.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1247
Message-Id: <20251008100222.4610-1-gert@greenie.muc.de>
URL: https://sourceforge.net/p/openvpn/mailman/message/59243809/
Signed-off-by: Gert Doering <gert@greenie.muc.de>
| ... | ... |
@@ -43,6 +43,9 @@ __wrap_add_option(struct options *options, char *p[], bool is_inline, const char |
| 43 | 43 |
const unsigned int permission_mask, unsigned int *option_types_found, |
| 44 | 44 |
struct env_set *es) |
| 45 | 45 |
{
|
| 46 |
+ function_called(); |
|
| 47 |
+ check_expected(p); |
|
| 48 |
+ check_expected(is_inline); |
|
| 46 | 49 |
} |
| 47 | 50 |
|
| 48 | 51 |
void |
| ... | ... |
@@ -185,11 +188,117 @@ test_parse_line(void **state) |
| 185 | 185 |
gc_free(&gc); |
| 186 | 186 |
} |
| 187 | 187 |
|
| 188 |
+static void |
|
| 189 |
+read_single_config(struct options *options, const char *config) |
|
| 190 |
+{
|
|
| 191 |
+ unsigned int option_types_found = 0; |
|
| 192 |
+ struct env_set es; |
|
| 193 |
+ CLEAR(es); |
|
| 194 |
+ read_config_string("test_options_parse", options, config, M_INFO, OPT_P_DEFAULT,
|
|
| 195 |
+ &option_types_found, &es); |
|
| 196 |
+} |
|
| 197 |
+ |
|
| 198 |
+union tokens_parameter |
|
| 199 |
+{
|
|
| 200 |
+ uintmax_t as_int; |
|
| 201 |
+ void *as_pointer; |
|
| 202 |
+}; |
|
| 203 |
+ |
|
| 204 |
+static int |
|
| 205 |
+check_tokens(const uintmax_t value, const uintmax_t expected) |
|
| 206 |
+{
|
|
| 207 |
+ union tokens_parameter temp; |
|
| 208 |
+ temp.as_int = value; |
|
| 209 |
+ const char **p = (const char **)temp.as_pointer; |
|
| 210 |
+ temp.as_int = expected; |
|
| 211 |
+ const char **expected_p = (const char **)temp.as_pointer; |
|
| 212 |
+ for (int i = 0; i < MAX_PARMS; i++) |
|
| 213 |
+ {
|
|
| 214 |
+ if (!p[i] && !expected_p[i]) |
|
| 215 |
+ {
|
|
| 216 |
+ return true; |
|
| 217 |
+ } |
|
| 218 |
+ if ((p[i] && !expected_p[i]) |
|
| 219 |
+ || (!p[i] && expected_p[i])) |
|
| 220 |
+ {
|
|
| 221 |
+ fprintf(stderr, "diff at i=%d\n", i); |
|
| 222 |
+ return false; |
|
| 223 |
+ } |
|
| 224 |
+ if (strcmp(p[i], expected_p[i])) |
|
| 225 |
+ {
|
|
| 226 |
+ fprintf(stderr, "diff at i=%d, p=<%s> ep=<%s>\n", i, p[i], expected_p[i]); |
|
| 227 |
+ return false; |
|
| 228 |
+ } |
|
| 229 |
+ } |
|
| 230 |
+ fprintf(stderr, "fallthrough"); |
|
| 231 |
+ return false; |
|
| 232 |
+} |
|
| 233 |
+ |
|
| 234 |
+static void |
|
| 235 |
+test_read_config(void **state) |
|
| 236 |
+{
|
|
| 237 |
+ struct options o; |
|
| 238 |
+ CLEAR(o); /* NB: avoiding init_options to limit dependencies */ |
|
| 239 |
+ gc_init(&o.gc); |
|
| 240 |
+ gc_init(&o.dns_options.gc); |
|
| 241 |
+ o.gc_owned = true; |
|
| 242 |
+ |
|
| 243 |
+ char *p_expect_someopt[MAX_PARMS]; |
|
| 244 |
+ char *p_expect_otheropt[MAX_PARMS]; |
|
| 245 |
+ char *p_expect_inlineopt[MAX_PARMS]; |
|
| 246 |
+ CLEAR(p_expect_someopt); |
|
| 247 |
+ CLEAR(p_expect_otheropt); |
|
| 248 |
+ CLEAR(p_expect_inlineopt); |
|
| 249 |
+ p_expect_someopt[0] = "someopt"; |
|
| 250 |
+ p_expect_someopt[1] = "parm1"; |
|
| 251 |
+ p_expect_someopt[2] = "parm2"; |
|
| 252 |
+ p_expect_otheropt[0] = "otheropt"; |
|
| 253 |
+ p_expect_otheropt[1] = "1"; |
|
| 254 |
+ p_expect_otheropt[2] = "2"; |
|
| 255 |
+ p_expect_inlineopt[0] = "inlineopt"; |
|
| 256 |
+ p_expect_inlineopt[1] = "some text\nother text\n"; |
|
| 257 |
+ |
|
| 258 |
+ /* basic test */ |
|
| 259 |
+ expect_function_call(__wrap_add_option); |
|
| 260 |
+ expect_check(__wrap_add_option, p, check_tokens, p_expect_someopt); |
|
| 261 |
+ expect_value(__wrap_add_option, is_inline, 0); |
|
| 262 |
+ expect_function_call(__wrap_add_option); |
|
| 263 |
+ expect_check(__wrap_add_option, p, check_tokens, p_expect_otheropt); |
|
| 264 |
+ expect_value(__wrap_add_option, is_inline, 0); |
|
| 265 |
+ read_single_config(&o, "someopt parm1 parm2\n otheropt 1 2"); |
|
| 266 |
+ |
|
| 267 |
+ /* -- gets stripped */ |
|
| 268 |
+ expect_function_call(__wrap_add_option); |
|
| 269 |
+ expect_check(__wrap_add_option, p, check_tokens, p_expect_someopt); |
|
| 270 |
+ expect_value(__wrap_add_option, is_inline, 0); |
|
| 271 |
+ expect_function_call(__wrap_add_option); |
|
| 272 |
+ expect_check(__wrap_add_option, p, check_tokens, p_expect_otheropt); |
|
| 273 |
+ expect_value(__wrap_add_option, is_inline, 0); |
|
| 274 |
+ read_single_config(&o, "someopt parm1 parm2\n\t--otheropt 1 2"); |
|
| 275 |
+ |
|
| 276 |
+ /* inline options */ |
|
| 277 |
+ expect_function_call(__wrap_add_option); |
|
| 278 |
+ expect_check(__wrap_add_option, p, check_tokens, p_expect_inlineopt); |
|
| 279 |
+ expect_value(__wrap_add_option, is_inline, 1); |
|
| 280 |
+ read_single_config(&o, "<inlineopt>\nsome text\nother text\n</inlineopt>"); |
|
| 281 |
+ |
|
| 282 |
+ p_expect_inlineopt[0] = "inlineopt"; |
|
| 283 |
+ p_expect_inlineopt[1] = A_TIMES_256 A_TIMES_256 A_TIMES_256 A_TIMES_256 A_TIMES_256 "\n"; |
|
| 284 |
+ expect_function_call(__wrap_add_option); |
|
| 285 |
+ expect_check(__wrap_add_option, p, check_tokens, p_expect_inlineopt); |
|
| 286 |
+ expect_value(__wrap_add_option, is_inline, 1); |
|
| 287 |
+ read_single_config(&o, "<inlineopt>\n" A_TIMES_256 A_TIMES_256 A_TIMES_256 A_TIMES_256 A_TIMES_256 "\n</inlineopt>"); |
|
| 288 |
+ |
|
| 289 |
+ gc_free(&o.gc); |
|
| 290 |
+ gc_free(&o.dns_options.gc); |
|
| 291 |
+} |
|
| 292 |
+ |
|
| 188 | 293 |
int |
| 189 | 294 |
main(void) |
| 190 | 295 |
{
|
| 191 | 296 |
const struct CMUnitTest tests[] = {
|
| 192 | 297 |
cmocka_unit_test(test_parse_line), |
| 298 |
+ cmocka_unit_test(test_read_config), |
|
| 193 | 299 |
}; |
| 194 | 300 |
|
| 195 | 301 |
return cmocka_run_group_tests_name("options_parse", tests, NULL, NULL);
|