Fix a memory leak in aname_replacer using the recommended flow control
authorGreg Hudson <ghudson@mit.edu>
Tue, 28 Apr 2009 04:46:10 +0000 (04:46 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 28 Apr 2009 04:46:10 +0000 (04:46 +0000)
for exception handling.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22285 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/an_to_ln.c

index 03b9b2d7c167740fcbffc7305c2fd7e04363ebc2..ed9bc96ca642ebcf08225c3da409d33a25dc5688 100644 (file)
@@ -376,103 +376,108 @@ static krb5_error_code
 aname_replacer(char *string, char **contextp, char **result)
 {
     krb5_error_code    kret;
-    char               *in;
-    char               *out;
+    char               *in = NULL, *out = NULL, *rule = NULL, *repl = NULL;
     char               *cp, *ep, *tp;
-    char               *rule, *repl;
     size_t             rule_size, repl_size;
     int                        doglobal;
 
-    kret = ENOMEM;
-    *result = (char *) NULL;
+    *result = NULL;
+
     /* Allocate the formatting buffers */
-    if ((in = (char *) malloc(MAX_FORMAT_BUFFER)) &&
-       (out = (char *) malloc(MAX_FORMAT_BUFFER))) {
-       /*
-        * Prime the buffers.  Copy input string to "out" to simulate it
-        * being the result of an initial iteration.
-        */
-       strncpy(out, string, MAX_FORMAT_BUFFER - 1);
-       out[MAX_FORMAT_BUFFER - 1] = '\0';
-       in[0] = '\0';
-       kret = 0;
+    in = malloc(MAX_FORMAT_BUFFER);
+    if (!in)
+       return ENOMEM;
+    out = malloc(MAX_FORMAT_BUFFER);
+    if (!out) {
+       kret = ENOMEM;
+       goto cleanup;
+    }
+
+    /*
+     * Prime the buffers.  Copy input string to "out" to simulate it
+     * being the result of an initial iteration.
+     */
+    strlcpy(out, string, MAX_FORMAT_BUFFER);
+    in[0] = '\0';
+    kret = 0;
+    /*
+     * Pound through the expression until we're done.
+     */
+    for (cp = *contextp; *cp; ) {
+       /* Skip leading whitespace */
+       while (isspace((int) (*cp)))
+           cp++;
+
        /*
-        * Pound through the expression until we're done.
+        * Find our separators.  First two characters must be "s/"
+        * We must also find another "/" followed by another "/".
         */
-       for (cp = *contextp; *cp; ) {
-           /* Skip leading whitespace */
-           while (isspace((int) (*cp)))
-               cp++;
-
-           /*
-            * Find our separators.  First two characters must be "s/"
-            * We must also find another "/" followed by another "/".
-            */
-           if ((cp[0] == 's') &&
-               (cp[1] == '/') &&
-               (ep = strchr(&cp[2], '/')) &&
-               (tp = strchr(&ep[1], '/'))) {
-
-               /* Figure out sizes of strings and allocate them */
-               rule_size = (size_t) (ep - &cp[2]);
-               repl_size = (size_t) (tp - &ep[1]);
-               if ((rule = (char *) malloc(rule_size+1)) &&
-                   (repl = (char *) malloc(repl_size+1))) {
-
-                   /* Copy the strings */
-                   strncpy(rule, &cp[2], rule_size);
-                   strncpy(repl, &ep[1], repl_size);
-                   rule[rule_size] = repl[repl_size] = '\0';
-
-                   /* Check for trailing "g" */
-                   doglobal = (tp[1] == 'g') ? 1 : 0;
-                   if (doglobal)
-                       tp++;
-
-                   /* Swap previous in and out buffers */
-                   ep = in;
-                   in = out;
-                   out = ep;
-
-                   /* Do the replacemenbt */
-                   memset(out, '\0', MAX_FORMAT_BUFFER);
-                   if (!do_replacement(rule, repl, doglobal, in, out)) {
-                       free(rule);
-                       free(repl);
-                       kret = KRB5_LNAME_NOTRANS;
-                       break;
-                   }
-                   free(rule);
-                   free(repl);
+       if (!((cp[0] == 's') &&
+             (cp[1] == '/') &&
+             (ep = strchr(&cp[2], '/')) &&
+             (tp = strchr(&ep[1], '/')))) {
+           /* Bad syntax */
+           kret = KRB5_CONFIG_BADFORMAT;
+           goto cleanup;
+       }
 
-                   /* If we have no output buffer left, this can't be good */
-                   if (strlen(out) == 0) {
-                       kret = KRB5_LNAME_NOTRANS;
-                       break;
-                   }
-               }
-               else {
-                   /* No memory for copies */
-                   free(rule);
-                   kret = ENOMEM;
-                   break;
-               }
-           }
-           else {
-               /* Bad syntax */
-               kret = KRB5_CONFIG_BADFORMAT;
-               break;
-           }
-           /* Advance past trailer */
-           cp = &tp[1];
+       /* Figure out sizes of strings and allocate them */
+       rule_size = (size_t) (ep - &cp[2]);
+       repl_size = (size_t) (tp - &ep[1]);
+       rule = malloc(rule_size + 1);
+       if (!rule) {
+           kret = ENOMEM;
+           goto cleanup;
        }
-       free(in);
-       if (!kret)
-           *result = out;
-       else
-           free(out);
+       repl = malloc(repl_size + 1);
+       if (!repl) {
+           kret = ENOMEM;
+           goto cleanup;
+       }
+
+       /* Copy the strings */
+       memcpy(rule, &cp[2], rule_size);
+       memcpy(repl, &ep[1], repl_size);
+       rule[rule_size] = repl[repl_size] = '\0';
+
+       /* Check for trailing "g" */
+       doglobal = (tp[1] == 'g') ? 1 : 0;
+       if (doglobal)
+           tp++;
+
+       /* Swap previous in and out buffers */
+       ep = in;
+       in = out;
+       out = ep;
+
+       /* Do the replacemenbt */
+       memset(out, '\0', MAX_FORMAT_BUFFER);
+       if (!do_replacement(rule, repl, doglobal, in, out)) {
+           kret = KRB5_LNAME_NOTRANS;
+           goto cleanup;
+       }
+       free(rule);
+       free(repl);
+       rule = repl = NULL;
+
+       /* If we have no output buffer left, this can't be good */
+       if (strlen(out) == 0) {
+           kret = KRB5_LNAME_NOTRANS;
+           goto cleanup;
+       }
+
+       /* Advance past trailer */
+       cp = &tp[1];
     }
-    return(kret);
+    free(in);
+    *result = out;
+    return 0;
+cleanup:
+    free(in);
+    free(out);
+    free(repl);
+    free(rule);
+    return kret;
 }
 
 /*