Index: src/blob.c
==================================================================
--- src/blob.c
+++ src/blob.c
@@ -894,11 +894,11 @@
 */
 int blob_uncompress(Blob *pIn, Blob *pOut){
   unsigned int nOut;
   unsigned char *inBuf;
   unsigned int nIn = blob_size(pIn);
-  Blob temp;
+  Blob temp = empty_blob;
   int rc;
   unsigned long int nOut2;
   if( nIn<=4 ){
     return 0;
   }

Index: src/content.c
==================================================================
--- src/content.c
+++ src/content.c
@@ -95,11 +95,11 @@
   p = &contentCache.a[contentCache.n++];
   p->rid = rid;
   p->age = contentCache.nextAge++;
   contentCache.szTotal += blob_size(pBlob);
   p->content = *pBlob;
-  blob_zero(pBlob);
+  *pBlob = empty_blob;
   bag_insert(&contentCache.inCache, rid);
 }
 
 /*
 ** Clear the content cache.
@@ -259,11 +259,11 @@
   }else{
     int n = 1;
     int nAlloc = 10;
     int *a = 0;
     int mx;
-    Blob delta, next;
+    Blob delta = empty_blob, next = empty_blob;
 
     a = fossil_malloc( sizeof(a[0])*nAlloc );
     a[0] = rid;
     a[1] = nextRid;
     n = 1;

Index: src/db.c
==================================================================
--- src/db.c
+++ src/db.c
@@ -211,11 +211,11 @@
 ** one is processed.  All statements beyond the first are silently ignored.
 */
 int db_vprepare(Stmt *pStmt, int errOk, const char *zFormat, va_list ap){
   int rc;
   char *zSql;
-  blob_zero(&pStmt->sql);
+  pStmt->sql = empty_blob;
   blob_vappendf(&pStmt->sql, zFormat, ap);
   va_end(ap);
   zSql = blob_str(&pStmt->sql);
   nPrepare++;
   rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0);

Index: src/deltacmd.c
==================================================================
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -77,11 +77,11 @@
 **
 ** Return the length of the target.  Return -1 if there is an error.
 */
 int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
   int len, n;
-  Blob out;
+  Blob out = empty_blob;
 
   n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
   blob_zero(&out);
   if( n<0 ) return -1;
   blob_resize(&out, n);

Index: src/diff.c
==================================================================
--- src/diff.c
+++ src/diff.c
@@ -619,10 +619,24 @@
 /**************************************************************************
 ** The basic difference engine is above.  What follows is the annotation
 ** engine.  Both are in the same file since they share many components.
 */
 
+/*
+** Linked list of strings, labels used in the annotator code.
+** The elements of the list and the pointed string (str)
+** will be freed once they become totally unreferenced
+** (nref == 0).
+*/
+struct Label
+{
+    struct Label *prev;   /* previous element */
+    struct Label *next;   /* next element */
+    char *str;            /* The label string */
+    int nref;             /* Number of references to the string */
+};
+
 /*
 ** The status of an annotation operation is recorded by an instance
 ** of the following structure.
 */
 typedef struct Annotator Annotator;
@@ -630,29 +644,31 @@
   DContext c;       /* The diff-engine context */
   struct AnnLine {  /* Lines of the original files... */
     const char *z;       /* The text of the line */
     short int n;         /* Number of bytes (omitting trailing space and \n) */
     short int iLevel;    /* Level at which tag was set */
-    const char *zSrc;    /* Tag showing origin of this line */
+    struct Label *zSrc;    /* Tag showing origin of this line */
   } *aOrig;
   int nOrig;        /* Number of elements in aOrig[] */
   int nNoSrc;       /* Number of entries where aOrig[].zSrc==NULL */
   int iLevel;       /* Current level */
   int nVers;        /* Number of versions analyzed */
-  char **azVers;    /* Names of versions analyzed */
+  struct Label **azVers;    /* Names of versions analyzed */
+  Blob toAnnotate;
+  struct Label *firstLabel;
 };
 
 /*
 ** Initialize the annotation process by specifying the file that is
 ** to be annotated.  The annotator takes control of the input Blob and
 ** will release it when it is finished with it.
 */
-static int annotation_start(Annotator *p, Blob *pInput){
+static int annotation_start(Annotator *p){
   int i;
 
-  memset(p, 0, sizeof(*p));
-  p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1);
+  p->c.aTo = break_into_lines(blob_str(&p->toAnnotate),
+          blob_size(&p->toAnnotate),&p->c.nTo,1);
   if( p->c.aTo==0 ){
     return 1;
   }
   p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
   for(i=0; i<p->c.nTo; i++){
@@ -669,20 +685,21 @@
 ** being annotated.  Do another step of the annotation.  Return true
 ** if additional annotation is required.  zPName is the tag to insert
 ** on each line of the file being annotated that was contributed by
 ** pParent.  Memory to hold zPName is leaked.
 */
-static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
+static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){
   int i, j;
   int lnTo;
   int iPrevLevel;
   int iThisLevel;
 
   /* Prepare the parent file to be diffed */
   p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
                                 &p->c.nFrom, 1);
   if( p->c.aFrom==0 ){
+    free(p->c.aFrom);
     return 1;
   }
 
   /* Compute the differences going from pParent to the file being
   ** annotated. */
@@ -696,11 +713,24 @@
   iThisLevel = p->iLevel;
   for(i=lnTo=0; i<p->c.nEdit; i+=3){
     struct AnnLine *x = &p->aOrig[lnTo];
     for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
       if( x->zSrc==0 || x->iLevel==iPrevLevel ){
+         if (x->zSrc!=0)
+         {
+           if(--x->zSrc->nref == 0)
+           {
+             free(x->zSrc->str);
+             if (x->zSrc->prev)
+               x->zSrc->prev->next = x->zSrc->next;
+             if (x->zSrc->next)
+               x->zSrc->next->prev = x->zSrc->prev;
+             free(x->zSrc);
+           }
+         }
          x->zSrc = zPName;
+         ++zPName->nref;
          x->iLevel = iThisLevel;
       }
     }
     lnTo += p->c.aEdit[i+2];
   }
@@ -711,11 +741,11 @@
   p->c.nEdit = 0;
   p->c.nEditAlloc = 0;
 
   /* Clear out the from file */
   free(p->c.aFrom);    
-  blob_zero(pParent);
+  blob_reset(pParent);
 
   /* Return no errors */
   return 0;
 }
 
@@ -722,32 +752,49 @@
 
 /*
 ** COMMAND: test-annotate-step
 */
 void test_annotate_step_cmd(void){
-  Blob orig, b;
+  Blob b = empty_blob;
   Annotator x;
   int i;
 
   if( g.argc<4 ) usage("RID1 RID2 ...");
   db_must_be_within_tree();
-  blob_zero(&b);
-  content_get(name_to_rid(g.argv[2]), &orig);
-  if( annotation_start(&x, &orig) ){
+  memset(&x, 0, sizeof(x));
+  x.toAnnotate = empty_blob;
+  content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
+  if( annotation_start(&x) ){
     fossil_fatal("binary file");
   }
   for(i=3; i<g.argc; i++){
+    struct Label *l;
     blob_zero(&b);
     content_get(name_to_rid(g.argv[i]), &b);
-    if( annotation_step(&x, &b, g.argv[i-1]) ){
+    l = fossil_malloc(sizeof(*l));
+    l->str = g.argv[i-1];
+    l->nref = 0;
+    l->next = x.firstLabel;
+    if (x.firstLabel)
+      x.firstLabel->prev = l;
+    x.firstLabel = l;
+    if( annotation_step(&x, &b, l) ){
       fossil_fatal("binary file");
     }
   }
   for(i=0; i<x.nOrig; i++){
-    const char *zSrc = x.aOrig[i].zSrc;
+    const char *zSrc = x.aOrig[i].zSrc->str;
     if( zSrc==0 ) zSrc = g.argv[g.argc-1];
     fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
+  }
+  while(x.firstLabel) {
+    struct Label *l;
+    l = x.firstLabel->next;
+    assert(x.firstLabel->nref > 0);
+    free(x.firstLabel->str);
+    free(x.firstLabel);
+    x.firstLabel = l;
   }
 }
 
 /* Annotation flags */
 #define ANN_FILE_VERS  0x001  /* Show file version rather than commit version */
@@ -763,28 +810,28 @@
   int mid,             /* Use the version of the file in this check-in */
   int webLabel,        /* Use web-style annotations if true */
   int iLimit,          /* Limit the number of levels if greater than zero */
   int annFlags         /* Flags to alter the annotation */
 ){
-  Blob toAnnotate;     /* Text of the final (mid) version of the file */
-  Blob step;           /* Text of previous revision */
+  Blob step = empty_blob;           /* Text of previous revision */
   int rid;             /* Artifact ID of the file being annotated */
-  char *zLabel;        /* Label to apply to a line */
   Stmt q;              /* Query returning all ancestor versions */
 
   /* Initialize the annotation */
   rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
   if( rid==0 ){
     fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid);
   }
-  if( !content_get(rid, &toAnnotate) ){
+  memset(p, 0, sizeof(*p));
+  p->toAnnotate = empty_blob;
+  if( !content_get(rid, &p->toAnnotate) ){
     fossil_panic("unable to retrieve content of artifact #%d", rid);
   }
   db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
   if( iLimit<=0 ) iLimit = 1000000000;
   compute_direct_ancestors(mid, iLimit);
-  annotation_start(p, &toAnnotate);
+  annotation_start(p);
 
   db_prepare(&q, 
     "SELECT mlink.fid,"
     "       (SELECT uuid FROM blob WHERE rid=mlink.%s),"
     "       date(event.mtime), "
@@ -802,26 +849,42 @@
   while( db_step(&q)==SQLITE_ROW ){
     int pid = db_column_int(&q, 0);
     const char *zUuid = db_column_text(&q, 1);
     const char *zDate = db_column_text(&q, 2);
     const char *zUser = db_column_text(&q, 3);
+    struct Label *l = fossil_malloc(sizeof(*l));
+    l->nref = 0;
+    l->next = p->firstLabel;
+    l->prev = 0;
+    if (p->firstLabel)
+      p->firstLabel->prev = l;
     if( webLabel ){
-      zLabel = mprintf(
+      l->str = mprintf(
           "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s", 
           g.zTop, zUuid, zUuid, zDate, zUser
       );
     }else{
-      zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
+      l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
     }
+    p->firstLabel = l;
     p->nVers++;
     p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
-    p->azVers[p->nVers-1] = zLabel;
+    p->azVers[p->nVers-1] = l;
     content_get(pid, &step);
-    annotation_step(p, &step, zLabel);
+    annotation_step(p, &step, l);
+    if (l->nref == 0)
+    {
+      free(l->str);
+      p->firstLabel = l->next;
+      if (l->next)
+        l->next->prev = 0;
+      free(l);
+    }
     blob_reset(&step);
   }
   db_finalize(&q);
+  free(p->c.aTo);
 }
 
 /*
 ** WEBPAGE: annotate
 **
@@ -853,23 +916,35 @@
   if( P("log") ){
     int i;
     @ <h2>Versions analyzed:</h2>
     @ <ol>
     for(i=0; i<ann.nVers; i++){
-      @ <li><tt>%s(ann.azVers[i])</tt></li>
+      @ <li><tt>%s(ann.azVers[i]->str)</tt></li>
     }
     @ </ol>
     @ <hr>
     @ <h2>Annotation:</h2>
   }
   @ <pre>
   for(i=0; i<ann.nOrig; i++){
     ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
-    @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
+    @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z)
   }
   @ </pre>
   style_footer();
+
+  free(ann.azVers);
+  free(ann.aOrig);
+  blob_reset(&ann.toAnnotate);
+  while(ann.firstLabel) {
+    struct Label *l;
+    l = ann.firstLabel->next;
+    assert(ann.firstLabel->nref > 0);
+    free(ann.firstLabel->str);
+    free(ann.firstLabel);
+    ann.firstLabel = l;
+  }
 }
 
 /*
 ** COMMAND: annotate
 **
@@ -885,11 +960,11 @@
 */
 void annotate_cmd(void){
   int fnid;         /* Filename ID */
   int fid;          /* File instance ID */
   int mid;          /* Manifest where file was checked in */
-  Blob treename;    /* FILENAME translated to canonical form */
+  Blob treename = empty_blob;    /* FILENAME translated to canonical form */
   char *zFilename;  /* Cannonical filename */
   Annotator ann;    /* The annotation of the file */
   int i;            /* Loop counter */
   const char *zLimit; /* The value to the --limit option */
   int iLimit;       /* How far back in time to look */
@@ -914,22 +989,34 @@
   }
   fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename);
   if( fid==0 ){
     fossil_fatal("not part of current checkout: %s", zFilename);
   }
+  blob_reset(&treename);
   mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
   if( mid==0 ){
     fossil_panic("unable to find manifest");
   }
   if( fileVers ) annFlags |= ANN_FILE_VERS;
   annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
   if( showLog ){
     for(i=0; i<ann.nVers; i++){
-      printf("version %3d: %s\n", i+1, ann.azVers[i]);
+      printf("version %3d: %s\n", i+1, ann.azVers[i]->str);
     }
     printf("---------------------------------------------------\n");
   }
   for(i=0; i<ann.nOrig; i++){
     fossil_print("%s: %.*s\n", 
-                 ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
+                 ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z);
+  }
+  free(ann.azVers);
+  free(ann.aOrig);
+  blob_reset(&ann.toAnnotate);
+  while(ann.firstLabel) {
+    struct Label *l;
+    l = ann.firstLabel->next;
+    assert(ann.firstLabel->nref > 0);
+    free(ann.firstLabel->str);
+    free(ann.firstLabel);
+    ann.firstLabel = l;
   }
 }

Index: src/file.c
==================================================================
--- src/file.c
+++ src/file.c
@@ -701,11 +701,11 @@
 **
 ** The root of the tree is defined by the g.zLocalRoot variable.
 */
 int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
   int n;
-  Blob full;
+  Blob full = empty_blob;
   int nFull;
   char *zFull;
 
   blob_zero(pOut);
   db_must_be_within_tree();