Commits

Armin Ronacher committed e886396

Removed these memory leaks.

(Thanks to Christophe Simonis <simonis.christophe@gmail.com> for an
additional fix.)

Comments (0)

Files changed (6)

 
 void free_result(result_t* result)
 {
+    free(result->revision);
+    free(result->branch);
     free(result);
 }
 
     _options = options;
 }
 
+int result_set_revision(result_t* result, const char *revision)
+{
+    if (result->revision)
+        free(result->revision);
+    result->revision = strdup(revision);
+    return !!result->revision;
+}
+
+int result_set_branch(result_t* result, const char *branch)
+{
+    if (result->branch)
+        free(result->branch);
+    result->branch = strdup(branch);
+    return !!result->branch;
+}
+
 vccontext_t* init_context(const char *name,
                           options_t* options,
                           int (*probe)(vccontext_t*),
     int modified;                       /* any local changes? */
 } result_t;
 
+int result_set_revision(result_t* result, const char *revision);
+int result_set_branch(result_t* result, const char *branch);
+
 typedef struct vccontext_t vccontext_t;
 struct vccontext_t {
     const char *name;                   /* name of the VC system */
 
     if (!read_first_line("CVS/Tag", buf, 1024)) {
         debug("unable to read CVS/Tag: assuming trunk");
-        result->branch = "trunk";
+        result_set_branch(result, "trunk");
     }
     else {
         debug("read first line of CVS/Tag: '%s'", buf);
         if (buf[0] == 'T') {
             /* there is a sticky tag and it's a branch tag */
-            result->branch = strdup(buf+1); /* XXX mem leak! */
+            result_set_branch(result, buf + 1);
         }
         else {
             /* non-branch sticky tag or sticky date */            
-            result->branch = "(unknown)";
+           result_set_branch(result, "(unknown)");
         }
     }
     return result;
             if (strncmp(prefix, buf, prefixlen) == 0) {
                 /* yep, we're on a known branch */
                 debug("read a head ref from .git/HEAD: '%s'", buf);
-                result->branch = strdup(buf + prefixlen); /* XXX mem leak! */
-                found_branch = 1;
+                if (result_set_branch(result, buf + prefixlen))
+                    found_branch = 1;
             }
             else {
                 /* if it's not a branch name, assume it is a commit ID */
                 debug(".git/HEAD doesn't look like a head ref: unknown branch");
-                result->branch = "(unknown)";
-                result->revision = strndup(buf, 12); /* XXX mem leak! */
+                result_set_branch(result, "(unknown)");
+                result_set_revision(result, buf);
             }
             if (context->options->show_revision && found_branch) {
                 char buf[1024];
                 strcat(filename, ".git/refs/heads/");
                 strncat(filename, result->branch, 1000);
                 if (read_first_line(filename, buf, 1024)) {
-                    result->revision = malloc(13); /* XXX mem leak! */
-                    strncpy(result->revision, buf, 12);
-                    result->revision[12] = '\0';
+                    buf[12] = '0';
+                    result_set_revision(result, buf);
                 }
             }
         }
 {
     const size_t NODEID_LEN = 20;
     char buf[NODEID_LEN * 2];
+    char rev[32];
     size_t readsize;
 
     if (!context->options->show_revision) return;
     readsize = read_file(".hg/dirstate", buf, NODEID_LEN * 2);
     if (readsize == NODEID_LEN * 2) {
         debug("read nodeids from .hg/dirstate");
-        result->revision = malloc(32);  /* XXX mem leak */
 
         // first parent
-        if (!sum_bytes((unsigned char *) buf, NODEID_LEN)) return;
-        dump_hex(buf, result->revision, 6);
+        if (!sum_bytes((unsigned char *) buf, NODEID_LEN)) goto push;
+        dump_hex(buf, rev, 6);
 
         // second parent
-        if (!sum_bytes((unsigned char *) buf + NODEID_LEN, NODEID_LEN)) return;
-        result->revision[12] = ',';
-        dump_hex(buf + NODEID_LEN, result->revision + 13, 6);
+        if (!sum_bytes((unsigned char *) buf + NODEID_LEN, NODEID_LEN)) goto push;
+        rev[12] = ',';
+        dump_hex(buf + NODEID_LEN, rev + 13, 6);
     }
     else {
         debug("failed to read from .hg/dirstate");
+        return;
     }
+
+push:
+    result_set_revision(result, rev);
 }
 
 static void
         if (!patch) return;
         patch += 1;
         debug("patch name found: '%s'", patch);
-        result->revision = strdup(patch);   /* XXX mem leak */
+        result_set_revision(result, patch);
     }
     else {
         debug("failed to read from .hg/patches/status: assuming no mq patch applied");
     // prefers bookmark because it tends to be more informative
     if (read_first_line(".hg/bookmarks.current", buf, 1024) && buf[0]) {
         debug("read first line from .hg/bookmarks.current: '%s'", buf);
-        result->branch = strdup(buf);  /* XXX mem leak */
+        result_set_branch(result, buf);
     }
     else if (read_first_line(".hg/branch", buf, 1024)) {
         debug("read first line from .hg/branch: '%s'", buf);
-        result->branch = strdup(buf);   /* XXX mem leak */
+        result_set_branch(result, buf);
     }
     else {
         debug("failed to read from .hg/branch: assuming default branch");
-        result->branch = "default";
+        result_set_branch(result, "default");
     }
 
     update_mq_info(context, result);
             }
             else {
                 // XML file format (working copy created by svn < 1.4)
-                char* rev = calloc(100, sizeof(char)); /* XXX leak */
+                char rev[100];
                 char* marker = "revision=";
                 char* p = NULL;
                 while (fgets(line, sizeof(line), fp))
                     return NULL;
                 }
                 if (sscanf(p, " %*[^\"]\"%[0-9]\"", rev) == 1) {
-                    result->revision = rev;
+                    result_set_revision(result, rev);
                     debug("read svn revision from .svn/entries: '%s'", rev);
                 }
             }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.