SBuf&
SBuf::assign(const char *S, size_type n)
{
+ const Locker blobKeeper(this, S);
debugs(24, 6, id << " from c-string, n=" << n << ")");
- Locker prevent_raw_memory_madness(this, S, n);
clear();
return append(S, n); //bounds checked in append()
}
SBuf&
SBuf::append(const SBuf &S)
{
- Locker prevent_raw_memory_madness(this, S.buf(), S.length());
+ const Locker blobKeeper(this, S.buf());
return lowAppend(S.buf(), S.length());
}
SBuf &
SBuf::append(const char * S, size_type Ssize)
{
+ const Locker blobKeeper(this, S);
if (S == NULL)
return *this;
if (Ssize == SBuf::npos)
Ssize = strlen(S);
debugs(24, 7, "from c-string to id " << id);
- Locker prevent_raw_memory_madness(this, S, Ssize);
// coverity[access_dbuff_in_call]
return lowAppend(S, Ssize);
}
SBuf&
SBuf::Printf(const char *fmt, ...)
{
- // with printf() an arg might be a dangerous char*
+ // with printf() the fmt or an arg might be a dangerous char*
// NP: cant rely on vappendf() Locker because of clear()
- Locker prevent_raw_memory_madness(this, buf(), length());
+ const Locker blobKeeper(this, buf());
va_list args;
va_start(args, fmt);
SBuf&
SBuf::vappendf(const char *fmt, va_list vargs)
{
+ // with (v)appendf() the fmt or an arg might be a dangerous char*
+ const Locker blobKeeper(this, buf());
+
Must(fmt != NULL);
int sz = 0;
//reserve twice the format-string size, it's a likely heuristic
size_type requiredSpaceEstimate = strlen(fmt)*2;
- // with appendf() an arg might be a dangerous char*
- Locker prevent_raw_memory_madness(this, buf(), length());
-
char *space = rawSpace(requiredSpaceEstimate);
#ifdef VA_COPY
va_list ap;
int
SBuf::scanf(const char *format, ...)
{
+ // with the format or an arg might be a dangerous char*
+ // that gets invalidated by c_str()
+ const Locker blobKeeper(this, buf());
+
va_list arg;
int rv;
++stats.scanf;
// TODO: possibly implement a replace() call
private:
+ /**
+ * Keeps SBuf's MemBlob alive in a blob-destroying context where
+ * a seemingly unrelated memory pointer may belong to the same blob.
+ * For [an extreme] example, consider: a.append(a).
+ * Compared to an SBuf temporary, this class is optimized to
+ * preserve blobs only if needed and to reduce debugging noise.
+ */
class Locker
{
public:
- Locker(SBuf *parent, const char *Q, size_t len) : locket(nullptr) {
- // lock if Q intersects the parents buffer area
- const MemBlob *P = parent->store_.getRaw();
- if ( (Q+len) >= P->mem && Q <= (P->mem + P->capacity) )
- locket = P;
+ Locker(SBuf *parent, const char *otherBuffer) {
+ // lock if otherBuffer intersects the parents buffer area
+ const MemBlob *blob = parent->store_.getRaw();
+ if (blob->mem <= otherBuffer && otherBuffer < (blob->mem + blob->capacity))
+ locket = blob;
}
private:
MemBlob::Pointer locket;