Commit 4bfbe0a1 authored by Stepan Palamarchuk's avatar Stepan Palamarchuk Committed by Facebook Github Bot

Add DCHECKs for checking that underlying IOBuf wasn't modified

Summary: Appending/prepending to IOBuf while iterating over it with Cursor is unsafe. This diff adds DCHECKs to catch such cases.

Reviewed By: yfeldblum

Differential Revision: D6735060

fbshipit-source-id: 7799facc52c53fabd83756ecb26a18c4ebd69677
parent a4306bcd
...@@ -96,10 +96,12 @@ class CursorBase { ...@@ -96,10 +96,12 @@ class CursorBase {
* Get the current Cursor position relative to the head of IOBuf chain. * Get the current Cursor position relative to the head of IOBuf chain.
*/ */
size_t getCurrentPosition() const { size_t getCurrentPosition() const {
dcheckIntegrity();
return (crtPos_ - crtBegin_) + absolutePos_; return (crtPos_ - crtBegin_) + absolutePos_;
} }
const uint8_t* data() const { const uint8_t* data() const {
dcheckIntegrity();
return crtPos_; return crtPos_;
} }
...@@ -112,6 +114,7 @@ class CursorBase { ...@@ -112,6 +114,7 @@ class CursorBase {
* pointing at the end of a buffer. * pointing at the end of a buffer.
*/ */
size_t length() const { size_t length() const {
dcheckIntegrity();
return crtEnd_ - crtPos_; return crtEnd_ - crtPos_;
} }
...@@ -152,6 +155,7 @@ class CursorBase { ...@@ -152,6 +155,7 @@ class CursorBase {
* Return true if the cursor is at the end of the entire IOBuf chain. * Return true if the cursor is at the end of the entire IOBuf chain.
*/ */
bool isAtEnd() const { bool isAtEnd() const {
dcheckIntegrity();
// Check for the simple cases first. // Check for the simple cases first.
if (crtPos_ != crtEnd_) { if (crtPos_ != crtEnd_) {
return false; return false;
...@@ -353,6 +357,7 @@ class CursorBase { ...@@ -353,6 +357,7 @@ class CursorBase {
void skipWhile(const Predicate& predicate); void skipWhile(const Predicate& predicate);
size_t skipAtMost(size_t len) { size_t skipAtMost(size_t len) {
dcheckIntegrity();
if (LIKELY(crtPos_ + len < crtEnd_)) { if (LIKELY(crtPos_ + len < crtEnd_)) {
crtPos_ += len; crtPos_ += len;
return len; return len;
...@@ -361,6 +366,7 @@ class CursorBase { ...@@ -361,6 +366,7 @@ class CursorBase {
} }
void skip(size_t len) { void skip(size_t len) {
dcheckIntegrity();
if (LIKELY(crtPos_ + len < crtEnd_)) { if (LIKELY(crtPos_ + len < crtEnd_)) {
crtPos_ += len; crtPos_ += len;
} else { } else {
...@@ -378,6 +384,7 @@ class CursorBase { ...@@ -378,6 +384,7 @@ class CursorBase {
} }
size_t retreatAtMost(size_t len) { size_t retreatAtMost(size_t len) {
dcheckIntegrity();
if (len <= static_cast<size_t>(crtPos_ - crtBegin_)) { if (len <= static_cast<size_t>(crtPos_ - crtBegin_)) {
crtPos_ -= len; crtPos_ -= len;
return len; return len;
...@@ -386,6 +393,7 @@ class CursorBase { ...@@ -386,6 +393,7 @@ class CursorBase {
} }
void retreat(size_t len) { void retreat(size_t len) {
dcheckIntegrity();
if (len <= static_cast<size_t>(crtPos_ - crtBegin_)) { if (len <= static_cast<size_t>(crtPos_ - crtBegin_)) {
crtPos_ -= len; crtPos_ -= len;
} else { } else {
...@@ -394,6 +402,7 @@ class CursorBase { ...@@ -394,6 +402,7 @@ class CursorBase {
} }
size_t pullAtMost(void* buf, size_t len) { size_t pullAtMost(void* buf, size_t len) {
dcheckIntegrity();
// Fast path: it all fits in one buffer. // Fast path: it all fits in one buffer.
if (LIKELY(crtPos_ + len <= crtEnd_)) { if (LIKELY(crtPos_ + len <= crtEnd_)) {
memcpy(buf, data(), len); memcpy(buf, data(), len);
...@@ -404,6 +413,7 @@ class CursorBase { ...@@ -404,6 +413,7 @@ class CursorBase {
} }
void pull(void* buf, size_t len) { void pull(void* buf, size_t len) {
dcheckIntegrity();
if (LIKELY(crtPos_ + len <= crtEnd_)) { if (LIKELY(crtPos_ + len <= crtEnd_)) {
memcpy(buf, data(), len); memcpy(buf, data(), len);
crtPos_ += len; crtPos_ += len;
...@@ -551,6 +561,14 @@ class CursorBase { ...@@ -551,6 +561,14 @@ class CursorBase {
} }
protected: protected:
void dcheckIntegrity() const {
DCHECK(crtBegin_ <= crtPos_ && crtPos_ <= crtEnd_);
DCHECK(crtBuf_ == nullptr || crtBegin_ == crtBuf_->data());
DCHECK(
crtBuf_ == nullptr ||
(uint64_t)(crtEnd_ - crtBegin_) == crtBuf_->length());
}
~CursorBase() { } ~CursorBase() { }
BufType* head() { BufType* head() {
...@@ -586,6 +604,7 @@ class CursorBase { ...@@ -586,6 +604,7 @@ class CursorBase {
} }
void advanceBufferIfEmpty() { void advanceBufferIfEmpty() {
dcheckIntegrity();
if (crtPos_ == crtEnd_) { if (crtPos_ == crtEnd_) {
tryAdvanceBuffer(); tryAdvanceBuffer();
} }
...@@ -822,6 +841,7 @@ class RWCursor ...@@ -822,6 +841,7 @@ class RWCursor
this->crtPos_ = this->crtBegin_ + offset; this->crtPos_ = this->crtBegin_ + offset;
} }
void gatherAtMost(size_t n) { void gatherAtMost(size_t n) {
this->dcheckIntegrity();
size_t size = std::min(n, this->totalLength()); size_t size = std::min(n, this->totalLength());
size_t offset = this->crtPos_ - this->crtBegin_; size_t offset = this->crtPos_ - this->crtBegin_;
this->crtBuf_->gather(offset + size); this->crtBuf_->gather(offset + size);
...@@ -867,6 +887,7 @@ class RWCursor ...@@ -867,6 +887,7 @@ class RWCursor
} }
void insert(std::unique_ptr<folly::IOBuf> buf) { void insert(std::unique_ptr<folly::IOBuf> buf) {
this->dcheckIntegrity();
this->absolutePos_ += buf->computeChainDataLength(); this->absolutePos_ += buf->computeChainDataLength();
if (this->crtPos_ == this->crtBegin_ && this->crtBuf_ != this->buffer_) { if (this->crtPos_ == this->crtBegin_ && this->crtBuf_ != this->buffer_) {
// Can just prepend // Can just prepend
...@@ -905,6 +926,7 @@ class RWCursor ...@@ -905,6 +926,7 @@ class RWCursor
} }
uint8_t* writableData() { uint8_t* writableData() {
this->dcheckIntegrity();
return this->crtBuf_->writableData() + (this->crtPos_ - this->crtBegin_); return this->crtBuf_->writableData() + (this->crtPos_ - this->crtBegin_);
} }
......
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