INN commit: trunk (8 files)

INN Commit rra at isc.org
Wed Jun 17 20:23:54 UTC 2009


    Date: Wednesday, June 17, 2009 @ 13:23:54
  Author: iulius
Revision: 8518

* Fixed a segfault when retrieving via HDR/XHDR/XPAT the contents
of an extra overview field absent from the headers of an article.
The NEWNEWS command was also affected on very rare cases.
Thanks to Tim Woodall for the bug report.

* HDR/XHDR/XPAT answers are now robust when the overview database
is inconsistent.  When the overview schema was modified without
the overview database being rebuilt, wrong results could be
returned for extra fields (especially a random portion of some
other header).  The desired header name is now explicitly searched
in the overview information.  In order to achieve that, the
overview_getheader() function was split into
overview_get_standard_header() and overview_get_extra_header().
It allows to search by index for standard headers and to
walk extra overview fields.

* Fixed a memory leak when requesting metadata information
(:bytes and :lines).

Modified:
  trunk/CONTRIBUTORS
  trunk/doc/pod/news.pod
  trunk/include/inn/ov.h
  trunk/include/inn/overview.h
  trunk/nnrpd/article.c
  trunk/nnrpd/newnews.c
  trunk/nnrpd/nnrpd.c
  trunk/storage/overdata.c

------------------------+
 CONTRIBUTORS           |    2 -
 doc/pod/news.pod       |   20 +++++++++++
 include/inn/ov.h       |    8 ++--
 include/inn/overview.h |    4 +-
 nnrpd/article.c        |   16 +++++----
 nnrpd/newnews.c        |    5 +-
 nnrpd/nnrpd.c          |    2 -
 storage/overdata.c     |   82 ++++++++++++++++++++++++++++++++---------------
 8 files changed, 97 insertions(+), 42 deletions(-)

Modified: CONTRIBUTORS
===================================================================
--- CONTRIBUTORS	2009-06-17 17:49:36 UTC (rev 8517)
+++ CONTRIBUTORS	2009-06-17 20:23:54 UTC (rev 8518)
@@ -270,4 +270,4 @@
 J. Thomas Halliley, Matija Nalis, Geraint A. Edwards, Alexander Bartolich,
 David Hlacik, Andreas Mattheiss, James Ralston, Wim Lewis, Johan van Selst,
 Wolfgang M. Weyand, Berend Reitsma, William Kronert, Petr Novopashenniy,
-Steve Crook, John F. Morse
+Steve Crook, John F. Morse, Tim Woodall

Modified: doc/pod/news.pod
===================================================================
--- doc/pod/news.pod	2009-06-17 17:49:36 UTC (rev 8517)
+++ doc/pod/news.pod	2009-06-17 20:23:54 UTC (rev 8518)
@@ -1,3 +1,23 @@
+=head1 Changes in 2.5.1
+
+=over 2
+
+=item *
+
+Fixed a segfault when retrieving via HDR/XHDR/XPAT the contents of an extra
+overview field absent from the headers of an article.  The NEWNEWS command
+was also affected on very rare cases.  Thanks to Tim Woodall for the bug report.
+
+=item *
+
+HDR/XHDR/XPAT answers are now robust when the overview database is
+inconsistent.  When the overview schema was modified without the overview
+database being rebuilt, wrong results could be returned for extra fields
+(especially a random portion of some other header).  The desired header
+name is now explicitly searched in the overview information.
+
+=back
+
 =head1 Upgrading from 2.4 to 2.5
 
 The following changes require your full attention because a manual intervention

Modified: include/inn/ov.h
===================================================================
--- include/inn/ov.h	2009-06-17 17:49:36 UTC (rev 8517)
+++ include/inn/ov.h	2009-06-17 20:23:54 UTC (rev 8518)
@@ -58,13 +58,13 @@
 int overview_index(const char *field, const struct vector *extra);
 struct cvector *overview_split(const char *line, size_t length,
 			       ARTNUM *number, struct cvector *vector);
-char *overview_getheader(const struct cvector *vector, unsigned int element,
-			 const struct vector *extra);
+char *overview_get_standard_header(const struct cvector *vector, unsigned int element);
+char *overview_get_extra_header(const struct cvector *vector, const char *header);
 
-/* offsets into vectors for standard overview headers */
+/* Offsets into vectors for standard overview headers. */
 #ifndef INN_OVERVIEW_H
 enum {
-    OVERVIEW_SUBJECT,
+    OVERVIEW_SUBJECT = 0,
     OVERVIEW_FROM,
     OVERVIEW_DATE,
     OVERVIEW_MESSAGE_ID,

Modified: include/inn/overview.h
===================================================================
--- include/inn/overview.h	2009-06-17 17:49:36 UTC (rev 8517)
+++ include/inn/overview.h	2009-06-17 20:23:54 UTC (rev 8518)
@@ -184,8 +184,8 @@
 int overview_index(const char *field, const struct vector *extra);
 struct cvector *overview_split(const char *line, size_t length,
 			       ARTNUM *number, struct cvector *vector);
-char *overview_getheader(const struct cvector *vector, unsigned int element,
-			 const struct vector *extra);
+char *overview_get_standard_header(const struct cvector *vector, unsigned int element);
+char *overview_get_extra_header(const struct cvector *vector, const char *header);
 
 END_DECLS
 

Modified: nnrpd/article.c
===================================================================
--- nnrpd/article.c	2009-06-17 17:49:36 UTC (rev 8517)
+++ nnrpd/article.c	2009-06-17 20:23:54 UTC (rev 8518)
@@ -992,8 +992,8 @@
             HasNotReplied = false;
         }
 
-	vector = overview_split(data, len, NULL, vector);
-	r = overview_getheader(vector, OVERVIEW_MESSAGE_ID, OVextra);
+        vector = overview_split(data, len, NULL, vector);
+        r = overview_get_standard_header(vector, OVERVIEW_MESSAGE_ID);
         if (r == NULL) {
             if (PERMaccessconf->nnrpdoverstats) {
                 gettimeofday(&stv, NULL);
@@ -1092,7 +1092,7 @@
     bool		IsBytes, IsLines;
     bool                IsMetaBytes, IsMetaLines;
     bool		DidReply, HasNotReplied;
-    char		*header;
+    const char		*header;
     char		*pattern;
     char		*text;
     int			Overview;
@@ -1133,9 +1133,9 @@
     /* Make these changes because our overview database does
      * not currently know metadata names. */
     if (IsMetaBytes)
-        header = xstrdup("Bytes");
+        header = "Bytes";
     if (IsMetaLines)
-        header = xstrdup("Lines");
+        header = "Lines";
 
     /* We only allow :bytes and :lines for metadata. */
     if (!IsMetaLines && !IsMetaBytes) {
@@ -1293,7 +1293,11 @@
                 HasNotReplied = false;
             }
 	    vector = overview_split(data, len, NULL, vector);
-	    p = overview_getheader(vector, Overview, OVextra);
+            if (Overview < OVERVIEW_MAX) {
+                p = overview_get_standard_header(vector, Overview);
+            } else {
+                p = overview_get_extra_header(vector, header);
+            }
 	    if (p != NULL) {
 		if (PERMaccessconf->virtualhost &&
 			   Overview == overhdr_xref) {

Modified: nnrpd/newnews.c
===================================================================
--- nnrpd/newnews.c	2009-06-17 17:49:36 UTC (rev 8517)
+++ nnrpd/newnews.c	2009-06-17 20:23:54 UTC (rev 8518)
@@ -128,6 +128,7 @@
 }
 
 static char **groups;
+static char xref_header[] = "Xref";
 
 static void
 process_newnews(char *group, bool AllGroups, time_t date)
@@ -185,7 +186,7 @@
 		    continue;
 		/* We only care about the newsgroup list here, virtual
 		 * hosting isn't relevant. */
-		p = overview_getheader(vector, overhdr_xref, OVextra);
+		p = overview_get_extra_header(vector, xref_header);
 	    }
 	    if (p == NULL)
 		continue;
@@ -195,7 +196,7 @@
 		continue;
 	    if (HaveSeen(AllGroups, group, groups, xrefs))
 		continue;
-	    p = overview_getheader(vector, OVERVIEW_MESSAGE_ID, OVextra);
+	    p = overview_get_standard_header(vector, OVERVIEW_MESSAGE_ID);
 	    if (p == NULL)
 		continue;
 

Modified: nnrpd/nnrpd.c
===================================================================
--- nnrpd/nnrpd.c	2009-06-17 17:49:36 UTC (rev 8517)
+++ nnrpd/nnrpd.c	2009-06-17 20:23:54 UTC (rev 8518)
@@ -801,7 +801,7 @@
     }
     OVextra = overview_extra_fields(false);
     if (OVextra == NULL) {
-	/* Overview_extra_fields should already have logged something
+	/* overview_extra_fields() should already have logged something
 	 * useful. */
 	Reply("%d NNTP server unavailable.  Try later!\r\n", NNTP_FAIL_TERMINATING);
 	ExitWithStats(1, true);

Modified: storage/overdata.c
===================================================================
--- storage/overdata.c	2009-06-17 17:49:36 UTC (rev 8517)
+++ storage/overdata.c	2009-06-17 20:23:54 UTC (rev 8518)
@@ -314,11 +314,11 @@
 /*
 **  Given an overview header line, split out a vector pointing at each
 **  of the components (within line), returning a pointer to the
-**  vector. If the vector initially passed in is NULL a new vector is
-**  created, else the existing one is filled in.
+**  vector.  If the vector initially passed in is NULL, a new vector is
+**  created, otherwise the existing one is filled in.
 **
 **  A member `n' of the vector is of length (vector->strings[n+1] -
-**  vector->strings[n] - 1). Note that the last member of the vector
+**  vector->strings[n] - 1).  Note that the last member of the vector
 **  will always point beyond (line + length).
 */
 struct cvector *
@@ -333,7 +333,7 @@
 	cvector_clear(vector);
     }
     while (line != NULL) {
-	/* the first field is the article number */
+	/* The first field is the article number. */
 	if (p == NULL) {
 	    if (number != NULL) {
 		*number = atoi(line);
@@ -343,15 +343,15 @@
 	}
 	p = memchr(line, '\t', length);
 	if (p != NULL) {
-	    /* skip over the tab */
+	    /* Skip over the tab. */
 	    ++p;
-	    /* and calculate the remaining length */
+	    /* And calculate the remaining length. */
 	    length -= (p - line);
 	} else {
-	    /* add in a pointer to beyond the end of the final
-	     * component, so you can always calculate the length.
-	     * overview lines are always terminated with \r\n, so the
-	     * -1 ends up chopping those off */
+	    /* Add in a pointer to beyond the end of the final
+	       component, so you can always calculate the length;
+	       overview lines are always terminated with \r\n, so the
+	       -1 ends up chopping those off. */
 	    cvector_add(vector, line + length - 1);
 	}
 	line = p;
@@ -362,31 +362,61 @@
 /*
 **  Given an overview vector (from overview_split), return a copy of
 **  the member which the caller is interested in (and must free).
+**  The name and order of standard overview fields are fixed so we
+**  can request them by their index.
 */
 char *
-overview_getheader(const struct cvector *vector, unsigned int element,
-		   const struct vector *extra)
+overview_get_standard_header(const struct cvector *vector, unsigned int element)
 {
     char *field = NULL;
     size_t len;
     const char *p;
-    size_t max = ARRAY_SIZE(fields) + extra->count - 1;
+    size_t max = ARRAY_SIZE(fields) - 1;
 
+    /* vector ends with an additional pointer beyond the end of the final
+       component.  It therefore has a count of elements increased by 1. */
     if ((element + 1) >= vector->count || element > max) {
-	warn("request for invalid overview field %d", element);
-	return NULL;
+        warn("request for invalid standard overview field %d", element);
+        return NULL;
     }
-    /* Note... this routine does not synthesise Newsgroups: on behalf
-     * of the caller... */
-    if (element >= ARRAY_SIZE(fields)) {
-	/* +2 for `: ' */
-	p = vector->strings[element] +
-	    strlen(extra->strings[element - ARRAY_SIZE(fields)]) + 2;
-	len = vector->strings[element + 1] - p - 1;
-    } else {
-	p = vector->strings[element];
-	len = vector->strings[element + 1] - vector->strings[element] - 1;
-    }
+
+    p = vector->strings[element];
+    len = vector->strings[element + 1] - vector->strings[element] - 1;
+
     field = xstrndup(p, len);
     return field;
 }
+
+/*
+**  Given an overview vector (from overview_split), return a copy of
+**  the member which the caller is interested in (and must free).
+**  The order of extra overview fields may vary so we walk all the
+**  extra headers to find the requested field.
+*/
+char *
+overview_get_extra_header(const struct cvector *vector, const char *header)
+{
+    char *field = NULL;
+    size_t i, len;
+    const char *p;
+    size_t headerlen = strlen(header);
+
+    /* vector ends with an additional pointer beyond the end of the final
+       component.  It therefore has a count of elements increased by 1. */
+    for (i = ARRAY_SIZE(fields); i < vector->count - 1; i++) {
+        if (strncasecmp(header, vector->strings[i], headerlen) == 0) {
+            p = vector->strings[i] + headerlen;
+            /* Check for ": " after the name of the header. */
+            if ((*p++ == ':') && (*p++ == ' ')) {
+                len = vector->strings[i + 1] - p - 1;
+
+                field = xstrndup(p, len);
+                return field;
+            }
+        }
+    }
+
+    /* The required header was not found in the extra overview fields. */
+    return NULL;
+}
+




More information about the inn-committers mailing list