Re: bug report: modlogan fails when given logfiles with very long urls

Henrik Christian Grove <[email protected]> Thu, 11 Aug 2005 17:06:27 +0200
Newsgroups gmane.comp.sysutils.modular-log-analyzer
Organization B-one
Message-ID <1123772788.18107.111.camel@cepheus>
--=-rBEN8efCm3tRUz4tBEY/
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

ons, 27 07 2005 kl. 17:15 +0200, skrev Christian:
> Henrik Christian Grove schrieb:
> > If I unpack it, and run `modlogan -c config/modlogan.conf <
> > prestat/httpd/access-02.log`, modlogan processes 5 records.
> >
> > If I unpack it, remove the first line of prestat/httpd/access-02.log
> > and the run the same command, modlogan processes 383 records.
> >
> > If I unpack it, and run `head -1 prestat/httpd/access-02.log| modlogan
> > -c config/modlogan.conf`, modlogan processes the single record it
> > gets.
> 
> thanks for your files; i could reproduce it now. i thought about
> something yesterday and now i tried it:
> 
> i trimmed your first line to *exactly* 4096 chars (from 83.108.160.88 to
> 54  [nb]" with the ' " ', the whole record) and running modlogan will
> only count 6 records. trimming the line to 4095 chars, all records are
> processed.
> 
> but that does not mean, modlogan does not *try* to process the following
> records. it does, because it complains when the following record is
> corrupted (e.g. remove one "-" from the next record), it just does not
> count it.

Yes, but it only processes the next 5 (or was it 6).

> but i don't know in which part of modlogan the limit exists
> (/src/processor/web/process.c?), maybe the author can comment on that..?

It's not a limit but the EOF handling that's wrong.

The problem only occurs when it's the first line that's longer than 4095
characters.

The error is in the mgets function found in src/mio.c.

The first time it's called the file has a buffer of 4096 bytes (it has
to have some size, so this isn't the error) and it fills that.

After that there's nothing special about the first invocation (there
shouldn't be).
It then looks for a newline character in the buffer, when it doesn't
find a newline it tries to refill the buffer and it does so by reading
(f->ibuf->size - f->ibuf->used) bytes, this makes sense in the general
case, as the most likely reason for not finding a newline is that buffer
is almost empty. But when the first line was longer than 4095 characters
(f->ibuf->size - f->ibuf->used) is 0, and when you ask for 0 bytes, you
get zero bytes (nothing surprising here). Now comes the problem: The
code then assumes that if we read 0 bytes, it's because we reached
end-of-file (but we've not even read the first line yet) and sets the
eof flag for the file. -- It then proceeds by searching for a newline,
not finding any, expands the buffer, reads data into it (this time it
works - effectively demonstrating that we hadn't reached end-of-file),
searches for a newline ... When it finds a newline it returns the line
found. The next time few times it's called it finds a newline in the
buffer before checking the eof flag, and therefore it returns those
lines. After a few iterations, no more newlines can be found in the
buffer, and it checks the eof flag and stops (instead of reading more
data into the buffer).

The attached patch solves it by not setting the eof flag if we asked for
0 bytes.

Comments and better fixes are welcome.

.Henrik

PS: Not having a function to read a line is one of the (many) reasons I
hate C.

-- 
Henrik Christian Grove <[email protected]>
B-one

--=-rBEN8efCm3tRUz4tBEY/
Content-Disposition: attachment; filename=modlogan.patch-1
Content-Type: text/plain; name=modlogan.patch-1; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

--- mio.c	2004-03-18 03:31:50.000000000 +0100
+++ mio.c-fixed	2005-08-11 17:01:58.090083896 +0200
@@ -344,7 +344,7 @@
 						f->ibuf->used += len;
 					} while (f->ibuf->used < f->ibuf->size && len != 0);
 					/* the read was 'empty' -> EOF */
-					if (len == 0) {
+					if ((len == 0) && (f->ibuf->size - f->ibuf->used)) {
 						f->eof = 1;
 					}
 					


--=-rBEN8efCm3tRUz4tBEY/
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: Quoted-printable

--
To unsubscribe, e-mail:   [email protected]
For additional commands, e-mail: [email protected]
--=-rBEN8efCm3tRUz4tBEY/--