]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Make copy of "foreach" variable
authorAlan T. DeKok <aland@freeradius.org>
Sat, 28 May 2011 10:48:25 +0000 (12:48 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 28 May 2011 10:48:25 +0000 (12:48 +0200)
This lets it be deleted or modified in the loop, without changing
the value of the variable being looped over.

i.e. the variable being looped over can't be modified.  But the
underlying attribute can be deleted or free'd, and the server
won't crash

src/main/modcall.c
src/main/xlat.c

index 01190ce7fcb597833b09a1288dd891f9149264e0..0c5168abc1d94a0be81b755e94b8a4508afb663d 100644 (file)
@@ -365,6 +365,12 @@ typedef struct modcall_stack {
 } modcall_stack;
 
 
+static void pairfree_wrapper(void *data)
+{
+       VALUE_PAIR **vp = (VALUE_PAIR **) data;
+       pairfree(vp);
+}
+
 /*
  *     Call a module, iteratively, with a local stack, rather than
  *     recursively.  What did Paul Graham say about Lisp...?
@@ -494,7 +500,8 @@ int modcall(int component, modcallable *c, REQUEST *request)
                        modgroup *g = mod_callabletogroup(child);
 
                        for (i = 0; i < 8; i++) {
-                               if (!request_data_get(request, radius_get_vp, i)) {
+                               if (!request_data_reference(request,
+                                                           radius_get_vp, i)) {
                                        depth = i;
                                        break;
                                }
@@ -511,6 +518,8 @@ int modcall(int component, modcallable *c, REQUEST *request)
                                        stack.pointer + 1, modcall_spaces,
                                        child->name);
                                while (vp) {
+                                       VALUE_PAIR *copy = NULL, **copy_p;
+
 #ifndef NDEBUG
                                        if (fr_debug_flag >= 2) {
                                                char buffer[1024];
@@ -520,8 +529,12 @@ int modcall(int component, modcallable *c, REQUEST *request)
                                        }
 #endif
 
+                                       copy = paircopy(vp);
+                                       copy_p = &copy;
+
                                        request_data_add(request, radius_get_vp,
-                                                        depth, vp, NULL);
+                                                        depth, copy_p,
+                                                        pairfree_wrapper);
 
                                        myresult = modcall(component,
                                                           g->children,
@@ -533,13 +546,21 @@ int modcall(int component, modcallable *c, REQUEST *request)
                                        vp = pairfind(vp->next,
                                                      vp->attribute,
                                                      vp->vendor);
-                               }
 
-                               /*
-                                *      Delete the cached attribute.
-                                */
-                               request_data_get(request, radius_get_vp, depth);
-                       }
+                                       /*
+                                        *      Delete the cached attribute,
+                                        *      if it exists.
+                                        */
+                                       if (copy) {
+                                               request_data_get(request,
+                                                                radius_get_vp,
+                                                                depth);
+                                               pairfree(&copy);
+                                       } else {
+                                               break;
+                                       }
+                               } /* loop over VPs */
+                       }  /* if the VP exists */
 
                        myresult = RLM_MODULE_OK;
                        goto handle_result;
index 57d3b5b00b93e6354b5ba9030d1c283be75898ff..adade272a4cdae631cd51bfe20b5ddf5e16b20d9 100644 (file)
@@ -464,21 +464,22 @@ static size_t xlat_integer(UNUSED void *instance, REQUEST *request,
  *     Dynamically translate for check:, request:, reply:, etc.
  */
 static size_t xlat_foreach(void *instance, REQUEST *request,
-                         char *fmt, char *out, size_t outlen,
-                         RADIUS_ESCAPE_STRING func)
+                          UNUSED char *fmt, char *out, size_t outlen,
+                          RADIUS_ESCAPE_STRING func)
 {
-       VALUE_PAIR      *vp;
+       VALUE_PAIR      **pvp;
 
        /*
         *      See modcall, "FOREACH" for how this works.
         */
-       vp = request_data_reference(request, radius_get_vp, *(int*) instance);
-       if (!vp) {
+       pvp = (VALUE_PAIR **) request_data_reference(request, radius_get_vp,
+                                                    *(int*) instance);
+       if (!pvp || !*pvp) {
                *out = '\0';
                return 0;
        }
 
-       return valuepair2str(out, outlen, vp, vp->type, func);  
+       return valuepair2str(out, outlen, (*pvp), (*pvp)->type, func);  
 }
 #endif