Fix infinite loop when parsing invalid DAP message.

This commit updates `ContentReader::read` to optionally close the
underlying `Reader` when a message is read that does not terminate
the DAP header immediately following the `Content-Length` header
field.

This fixes an infinite loop when parsing an invalid DAP message. In
particular, the infinite loop occurs when a cross-site HTTP request from
a browser running on the same host as a cppdap server is sent to the
server. As cross-site requests to the localhost can be triggered by
untrusted JavaScript, more validation of the DAP messages is required to
protect cppdap-based servers from malicious requests.

This commit introduces a new enum flag on both `Session` and
`ContentReader` to allow a user to indicate that the underlying `Reader`
should be closed when an invalid DAP message is received. The
server example has been updated to indicate that invalid messages
should result in closure of the underlying `Reader`.
This commit is contained in:
Dan McNulty
2023-07-05 10:29:38 -05:00
committed by Ben Clayton
parent 93d94a7d85
commit e3379ed8c9
6 changed files with 81 additions and 7 deletions

View File

@@ -103,6 +103,14 @@ ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) {
// Session
////////////////////////////////////////////////////////////////////////////////
// An enum flag that controls how the Session handles invalid data.
enum OnInvalidData {
// Ignore invalid data.
kIgnore,
// Close the underlying reader when invalid data is received.
kClose,
};
// Session implements a DAP client or server endpoint.
// The general usage is as follows:
// (1) Create a session with Session::create().
@@ -144,6 +152,9 @@ class Session {
// create() constructs and returns a new Session.
static std::unique_ptr<Session> create();
// Sets how the Session handles invalid data.
virtual void setOnInvalidData(OnInvalidData) = 0;
// onError() registers a error handler that will be called whenever a protocol
// error is encountered.
// Only one error handler can be bound at any given time, and later calls