Fixed bug #794: Excessive memory when searching the LoC only.
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 5 Jan 2007 20:33:05 +0000 (20:33 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 5 Jan 2007 20:33:05 +0000 (20:33 +0000)
The bug was due to a buffer overrun in reclist_insert. Basically
the size could exceed that of flatlist_size. Reason is that
for LoC (or other target) we get 15 records at a time. 7*15 =
105 > 100 (expected_maxrecs). The buffer overrun made relevance_newrec
allocate very large nmem block. After that the tried would eventually
make a bad ptr reference. reclist_insert now returns 0 if there
is not enough room for a new record. Function ingest_record sees that
and does not process the record further. This bug was not relatd to
UTF-8 problems.

src/pazpar2.c
src/reclists.c

index 049fa85..cb6a384 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pazpar2.c,v 1.14 2007-01-04 22:04:25 quinn Exp $ */;
+/* $Id: pazpar2.c,v 1.15 2007-01-05 20:33:05 adam Exp $ */;
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -431,6 +431,7 @@ static struct record *ingest_record(struct client *cl, Z_External *rec)
     if (!(mergekey = xmlGetProp(root, "mergekey")))
     {
         yaz_log(YLOG_WARN, "No mergekey found in record");
+        xmlFreeDoc(xdoc);
         return 0;
     }
 
@@ -446,6 +447,12 @@ static struct record *ingest_record(struct client *cl, Z_External *rec)
     res->merge_key = normalize_mergekey(mergekey_norm);
 
     head = reclist_insert(se->reclist, res);
+    if (!head)
+    {
+        /* no room for record */
+        xmlFreeDoc(xdoc);
+        return 0;
+    }
     relevance_newrec(se->relevance, head);
 
     for (n = root->children; n; n = n->next)
index 40f1d76..6bca856 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: reclists.c,v 1.1 2006-12-20 20:47:16 quinn Exp $
+ * $Id: reclists.c,v 1.2 2007-01-05 20:33:05 adam Exp $
  */
 
 #include <assert.h>
@@ -71,7 +71,7 @@ struct record *reclist_insert(struct reclist *l, struct record  *record)
 {
     unsigned int bucket;
     struct reclist_bucket **p;
-    struct record *head;
+    struct record *head = 0;
 
     bucket = hash((unsigned char*) record->merge_key) & l->hashmask;
     for (p = &l->hashtable[bucket]; *p; p = &(*p)->next)
@@ -86,14 +86,18 @@ struct record *reclist_insert(struct reclist *l, struct record  *record)
             break;
         }
     }
-    if (!*p) // We made it to the end of the bucket without finding match
+    if (!head && l->num_records < l->flatlist_size)
     {
-        struct reclist_bucket *new = nmem_malloc(l->nmem,
-                sizeof(struct reclist_bucket));
+        struct reclist_bucket *new =
+            nmem_malloc(l->nmem, sizeof(struct reclist_bucket));
+        
+        assert(!*p);
+        
         new->record = record;
         record->next_cluster = 0;
         new->next = 0;
         *p = new;
+        assert(l->num_records < l->flatlist_size);
         l->flatlist[l->num_records++] = record;
         head = record;
     }