From 7ce18cf5c766487c184322478d9a656ac63e1456 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 5 Jan 2007 20:33:05 +0000 Subject: [PATCH] Fixed bug #794: Excessive memory when searching the LoC only. 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 | 9 ++++++++- src/reclists.c | 14 +++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/pazpar2.c b/src/pazpar2.c index 049fa85..cb6a384 100644 --- a/src/pazpar2.c +++ b/src/pazpar2.c @@ -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 #include @@ -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) diff --git a/src/reclists.c b/src/reclists.c index 40f1d76..6bca856 100644 --- a/src/reclists.c +++ b/src/reclists.c @@ -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 @@ -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; } -- 1.7.10.4