INN commit: branches/2.5 (8 files)
INN Commit
rra at isc.org
Sat Jun 20 12:20:04 UTC 2009
Date: Saturday, June 20, 2009 @ 05:20:03
Author: iulius
Revision: 8519
* Fixed a memory allocation problem 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:
branches/2.5/CONTRIBUTORS
branches/2.5/doc/pod/news.pod
branches/2.5/include/inn/ov.h
branches/2.5/include/inn/overview.h
branches/2.5/nnrpd/article.c
branches/2.5/nnrpd/newnews.c
branches/2.5/nnrpd/nnrpd.c
branches/2.5/storage/overdata.c
------------------------+
CONTRIBUTORS | 2 -
doc/pod/news.pod | 21 ++++++++++++
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, 98 insertions(+), 42 deletions(-)
Modified: CONTRIBUTORS
===================================================================
--- CONTRIBUTORS 2009-06-17 20:23:54 UTC (rev 8518)
+++ CONTRIBUTORS 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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 20:23:54 UTC (rev 8518)
+++ doc/pod/news.pod 2009-06-20 12:20:03 UTC (rev 8519)
@@ -1,3 +1,24 @@
+=head1 Changes in 2.5.1
+
+=over 2
+
+=item *
+
+Fixed a memory allocation problem which caused B<nnrpd> to die 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 20:23:54 UTC (rev 8518)
+++ include/inn/ov.h 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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 20:23:54 UTC (rev 8518)
+++ include/inn/overview.h 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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 20:23:54 UTC (rev 8518)
+++ nnrpd/article.c 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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 20:23:54 UTC (rev 8518)
+++ nnrpd/newnews.c 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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 20:23:54 UTC (rev 8518)
+++ nnrpd/nnrpd.c 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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 20:23:54 UTC (rev 8518)
+++ storage/overdata.c 2009-06-20 12:20:03 UTC (rev 8519)
@@ -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