In src/plain.cc, \r\n sequences are handled with these lines: while ( i < MaxBytes ) { ... addLine(Start + i - len, len); if (Start[i] == '\r' && Start[i + 1] == '\n') ++i; if (i < MaxBytes) ++i; ... So if a \r occurs, skip over the \n if present. But if i + 1 == MaxBytes, Start[i + 1] is one past the end of the buffer, which is an out-of-bounds read. This happens if a file ends in \r, or I suppose if a file gets broken up and parsed with multiple invocations of the function. I think this could theoretically add a redundant line break to the rendered page. My diff fixes this. I have tested it with \r, \r\n, and \n line endings. I haven't been able to test how it behaves with plaintext pages that are parsed in multiple invocations, though. (Also, and this is unrelated but it bothers me: prefsparser.cc has a comment saying the `symbols` array is sorted, but it isn't.) diff --git a/src/plain.cc b/src/plain.cc index 0f5d6a48..e085ab19 100644 --- a/src/plain.cc +++ b/src/plain.cc @@ -142,7 +142,10 @@ void DilloPlain::addLine(char *Buf, uint_t BufSize) { int len; char buf[129]; - char *end = Buf + BufSize; + char *end; + + if (BufSize > 0 && Buf[BufSize - 1] == '\r') --BufSize; + end = Buf + BufSize; currentLine++; /* Start at 1 */ sprintf(buf, "L%ld", currentLine); /* Always fits */ @@ -181,7 +184,8 @@ void DilloPlain::write(void *Buf, uint_t BufSize, int Eof) while ( i < MaxBytes ) { switch ( state ) { case ST_SeekingEol: - if (Start[i] == '\n' || Start[i] == '\r') + if (Start[i] == '\n' || (Start[i] == '\r' && i + 1 < MaxBytes + && Start[i + 1] != '\n')) state = ST_Eol; else { ++i; ++len; @@ -189,8 +193,7 @@ void DilloPlain::write(void *Buf, uint_t BufSize, int Eof) break; case ST_Eol: addLine(Start + i - len, len); - if (Start[i] == '\r' && Start[i + 1] == '\n') ++i; - if (i < MaxBytes) ++i; + ++i; state = ST_SeekingEol; len = 0; break;