]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Don't allow "catch" by itself
authorAlan T. DeKok <aland@freeradius.org>
Mon, 21 Apr 2025 21:50:42 +0000 (17:50 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 21 Apr 2025 21:50:42 +0000 (17:50 -0400)
and add tests for it

src/lib/unlang/compile.c
src/tests/keywords/catch [new file with mode: 0644]

index 810c3d3802bf058fe3b124c02337062d523c8053..8db27b0bfa809b29739f1a7180a800b24f93220d 100644 (file)
@@ -2421,7 +2421,7 @@ static unlang_t *compile_try(unlang_t *parent, unlang_compile_t *unlang_ctx, CON
        CONF_SECTION *cs = cf_item_to_section(ci);
        unlang_group_t *g;
        unlang_t *c;
-       CONF_SECTION *next;
+       CONF_ITEM *next;
 
        static unlang_ext_t const ext = {
                .type = UNLANG_TYPE_TRY,
@@ -2442,8 +2442,11 @@ static unlang_t *compile_try(unlang_t *parent, unlang_compile_t *unlang_ctx, CON
                return NULL;
        }
 
-       next = cf_section_next(cf_item_to_section(cf_parent(cs)), cs);
-       if (!next || (strcmp(cf_section_name1(next), "catch") != 0)) {
+       next = cf_item_next(cf_parent(cs), ci);
+       while (next && cf_item_is_data(next)) next = cf_item_next(cf_parent(cs), next);
+
+       if (!next || !cf_item_is_section(next) ||
+           (strcmp(cf_section_name1(cf_item_to_section(next)), "catch") != 0)) {
                cf_log_err(cs, "'try' sections must be followed by a 'catch'");
                return NULL;
        }
@@ -2483,6 +2486,8 @@ static unlang_t *compile_catch(unlang_t *parent, unlang_compile_t *unlang_ctx, C
        unlang_group_t *g;
        unlang_t *c;
        unlang_catch_t *ca;
+       CONF_ITEM *prev;
+       char const *name;
 
        static unlang_ext_t const ext = {
                .type = UNLANG_TYPE_CATCH,
@@ -2490,6 +2495,26 @@ static unlang_t *compile_catch(unlang_t *parent, unlang_compile_t *unlang_ctx, C
                .type_name = "unlang_catch_t",
        };
 
+       prev = cf_item_prev(cf_parent(ci), ci);
+       while (prev && cf_item_is_data(prev)) prev = cf_item_prev(cf_parent(ci), prev);
+
+       if (!prev || !cf_item_is_section(prev)) {
+       fail:
+               cf_log_err(cs, "Found 'catch' section with no previous 'try'");
+               return NULL;
+       }
+
+       name = cf_section_name1(cf_item_to_section(prev));
+       fr_assert(name != NULL);
+
+       /*
+        *      The previous thing has to be a section.  And it has to
+        *      be either a "try" or a "catch".
+        */
+       if ((strcmp(name, "try") != 0) && (strcmp(name, "catch") != 0)) {
+               goto fail;
+       }
+
        g = group_allocate(parent, cs, &ext);
        if (!g) return NULL;
 
@@ -2509,7 +2534,8 @@ static unlang_t *compile_catch(unlang_t *parent, unlang_compile_t *unlang_ctx, C
 
        } else {
                int i;
-               char const *name = cf_section_name2(cs);
+
+               name = cf_section_name2(cs);
 
                if (catch_argv(cs, ca, name) < 0) {
                        talloc_free(c);
diff --git a/src/tests/keywords/catch b/src/tests/keywords/catch
new file mode 100644 (file)
index 0000000..46ba577
--- /dev/null
@@ -0,0 +1,5 @@
+User-Name := "foo"
+
+catch fail {   # ERROR
+      ok
+}
\ No newline at end of file