if (Config.onoff.relaxed_header_parser && tok.skipOne(CharacterSet::LF))
return true;
- return false;
+ if (tok.atEnd() || (tok.remaining().length() == 1 && tok.remaining().at(0) == '\r'))
+ return false; // need more data
+
+ throw TexcHere("garbage instead of CRLF line terminator");
+ return false; // unreachable, but make naive compilers happy
}
/// all characters except the LF line terminator
Http::StatusCode parseStatusCode;
protected:
- /// detect and skip the CRLF or (if tolerant) LF line terminator
- /// consume from the tokenizer and return true only if found
+ /**
+ * detect and skip the CRLF or (if tolerant) LF line terminator
+ * consume from the tokenizer.
+ *
+ * throws if non-terminator is detected.
+ * \retval true only if line terminator found.
+ * \retval false incomplete or missing line terminator, need more data.
+ */
bool skipLineTerminator(Http1::Tokenizer &tok) const;
/// the characters which are to be considered valid whitespace
// NOTE: any whitespace after the single SP is part of the reason phrase.
}
- if (tok.atEnd())
- return 0; // need more to be sure we have it all
-
/* RFC 7230 says we SHOULD ignore the reason phrase content
* but it has a definite valid vs invalid character set.
* We interpret the SHOULD as ignoring absence and syntax, but
// if we got here we are still looking for reason-phrase bytes
static const CharacterSet phraseChars = CharacterSet::WSP + CharacterSet::VCHAR + CharacterSet::OBSTEXT;
(void)tok.prefix(reasonPhrase_, phraseChars); // optional, no error if missing
- if (skipLineTerminator(tok)) {
- debugs(74, DBG_DATA, "parse remaining buf={length=" << tok.remaining().length() << ", data='" << tok.remaining() << "'}");
- buf_ = tok.remaining(); // resume checkpoint
- return 1;
- }
- reasonPhrase_.clear();
-
- if (tok.atEnd())
+ try {
+ if (skipLineTerminator(tok)) {
+ debugs(74, DBG_DATA, "parse remaining buf={length=" << tok.remaining().length() << ", data='" << tok.remaining() << "'}");
+ buf_ = tok.remaining(); // resume checkpoint
+ return 1;
+ }
+ reasonPhrase_.clear();
return 0; // need more to be sure we have it all
- debugs(74, 6, "invalid status-line. garbage in reason phrase.");
+ } catch (const std::exception &ex) {
+ debugs(74, 6, "invalid status-line: " << ex.what());
+ }
return -1;
}
buf_ = tok.remaining(); // parse checkpoint (unless there might be more token name)
}
- if (tok.atEnd())
- return false;
-
if (skipLineTerminator(tok)) {
buf_ = tok.remaining(); // checkpoint
// non-0 chunk means data, 0-size means optional Trailer follows
return true;
}
- throw TexcHere("corrupted chunk extension value");
return false;
}
theChunkSize = 0; // done with the current chunk
parsingStage_ = Http1::HTTP_PARSE_CHUNK_SZ;
return true;
-
- } else if (!tok.atEnd()) {
- throw TexcHere("found data between chunk end and CRLF");
}
return false;