Commit 77209caf by Puneetha Ramachandra Committed by Ben Clayton

Fix content reader for partial input

When there is partial message in reader, popping out the characters lead to parse errors on the subsequent attempt to parse. To avoid this, the last matched characters' index is stored during parsing and reset on error.
parent e53575d2
......@@ -44,13 +44,17 @@ void ContentReader::close() {
}
std::string ContentReader::read() {
matched_idx = 0;
// Find Content-Length header prefix
if (!scan("Content-Length:")) {
return "";
}
// Skip whitespace and tabs
while (matchAny(" \t")) {
}
// Parse length
size_t len = 0;
while (true) {
......@@ -68,10 +72,16 @@ std::string ContentReader::read() {
if (!match("\r\n\r\n")) {
return "";
}
// Read message
if (!buffer(len)) {
if (!buffer(len + matched_idx)) {
return "";
}
for (size_t i = 0; i < matched_idx; i++) {
buf.pop_front();
}
std::string out;
out.reserve(len);
for (size_t i = 0; i < len; i++) {
......@@ -97,18 +107,17 @@ bool ContentReader::scan(const char* str) {
}
bool ContentReader::match(const uint8_t* seq, size_t len) {
if (!buffer(len)) {
if (!buffer(len + matched_idx)) {
return false;
}
auto it = buf.begin();
auto it = matched_idx;
for (size_t i = 0; i < len; i++, it++) {
if (*it != seq[i]) {
if (buf[it] != seq[i]) {
return false;
}
}
for (size_t i = 0; i < len; i++) {
buf.pop_front();
}
matched_idx += len;
return true;
}
......@@ -118,12 +127,12 @@ bool ContentReader::match(const char* str) {
}
char ContentReader::matchAny(const char* chars) {
if (!buffer(1)) {
if (!buffer(1 + matched_idx)) {
return false;
}
int c = buf.front();
int c = buf[matched_idx];
if (auto p = strchr(chars, c)) {
buf.pop_front();
matched_idx++;
return *p;
}
return 0;
......@@ -177,4 +186,4 @@ bool ContentWriter::write(const std::string& msg) const {
writer->write(msg.data(), msg.size());
}
} // namespace dap
\ No newline at end of file
} // namespace dap
......@@ -47,6 +47,7 @@ class ContentReader {
std::shared_ptr<Reader> reader;
std::deque<uint8_t> buf;
uint32_t matched_idx = 0;
};
class ContentWriter {
......
......@@ -81,3 +81,19 @@ TEST(ContentStreamTest, ShortRead) {
ASSERT_EQ(cs.read(), "Content payload number three");
ASSERT_EQ(cs.read(), "");
}
TEST(ContentStreamTest, PartialReadAndParse) {
auto sb = std::make_shared<dap::StringBuffer>();
dap::ContentReader cs(sb);
sb->write("Content");
ASSERT_EQ(cs.read(), "");
sb->write("-Length: ");
ASSERT_EQ(cs.read(), "");
sb->write("26");
ASSERT_EQ(cs.read(), "");
sb->write("\r\n\r\n");
ASSERT_EQ(cs.read(), "");
sb->write("Content payload number one");
ASSERT_EQ(cs.read(), "Content payload number one");
ASSERT_EQ(cs.read(), "");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment