On 20/11/2013 1:19 a.m., Amos Jeffries wrote: > [ And here is the new patch. ] > > > This patch implements Alex's suggestion for step 1 of String removal by ... > > * Replace String class internal buffer with an SBuf. > * Move converters to/from String and SBuf from SBuf API to String API. > > > This method allows all String code to be converted quickly to SBuf > without so much worry about correct API conversion elsewhere around the > code since the wrapper provides exemplar cut-n-paste code to work from. > > Addition of a SBuf constructor and toSBuf() accessor to String allows > code using String to be converted directly to the SBuf API in smaller > portions later. These obsolete the SBuf API converters to String and > help reduce the SBuf API. > > > Notes for auditing: > Please audit this with a sole view of checking that the original > String:: API semantics and behaviour are unchanged by the internals > re-write. > This patch seeks to *avoid* several things which would normally take up > auditing time: > * fixing any bugs in the String API semantics or behaviour > * fixing any bugs in the code using String > * using correct C++ coding styles or patterns. > > These bugs, behaviour and coding usage checks will be done on the > following transition patches converting code variables from String to > SBuf type. > > Amos >
To avoid problems with NULL and defined() the callers of termedBuf() have been given an audit and updated to check for and cope with "" empty strings. And termedBuf() altered to return c_str() instead of NULL or c_str(). NP: there seems to be a regression in SBuf::rfind() which is preventing a fill unit-test run. But usage as a private proxy is not showing anything amiss. Amos
=== modified file 'src/Makefile.am' --- src/Makefile.am 2013-12-17 17:05:17 +0000 +++ src/Makefile.am 2013-12-19 10:45:53 +0000 @@ -23,7 +23,10 @@ SBuf.h \ SBuf.cc \ SBufExceptions.h \ - SBufExceptions.cc + SBufExceptions.cc \ + SquidString.h \ + String.cc \ + String.cci STOREMETA_SOURCE = \ StoreMeta.cc \ @@ -497,7 +500,6 @@ StatCounters.cc \ StatHist.h \ StatHist.cc \ - String.cc \ StrList.h \ StrList.cc \ stmem.cc \ @@ -589,8 +591,6 @@ MemBuf.h \ Store.cci \ StoreEntryStream.h \ - String.cci \ - SquidString.h \ SquidTime.h BUILT_SOURCES = \ @@ -728,11 +728,11 @@ MemBuf.cci \ MemBuf.h \ Parsing.h \ + $(SBUF_SOURCE) \ store_key_md5.h \ store_key_md5.cc \ tests/stub_StoreMeta.cc \ StoreMetaUnpacker.cc \ - String.cc \ SquidNew.cc \ tests/stub_time.cc \ ufsdump.cc \ @@ -1156,12 +1156,10 @@ Notes.cc \ Packer.cc \ Packer.h \ - SquidString.h \ SquidTime.h \ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ - String.cc \ StrList.h \ StrList.cc \ log/access_log.h \ @@ -1268,7 +1266,6 @@ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ - String.cc \ store_dir.cc \ StoreIOState.cc \ tests/stub_StoreMeta.cc \ @@ -1387,7 +1384,6 @@ HttpRequestMethod.cc \ Mem.h \ tests/stub_mem.cc \ - String.cc \ tests/testCacheManager.cc \ tests/testCacheManager.h \ tests/testMain.cc \ @@ -1703,7 +1699,6 @@ store_swapmeta.cc \ repl_modules.h \ store.cc \ - String.cc \ StrList.h \ StrList.cc \ tests/stub_SwapDir.cc \ @@ -1975,7 +1970,6 @@ tests/stub_StoreMeta.cc \ StoreMetaUnpacker.cc \ StoreSwapLogData.cc \ - String.cc \ tests/stub_SwapDir.cc \ tests/CapturingStoreEntry.h \ tests/testEvent.cc \ @@ -2220,7 +2214,6 @@ tests/stub_StoreMeta.cc \ StoreMetaUnpacker.cc \ StoreSwapLogData.cc \ - String.cc \ StrList.h \ StrList.cc \ tests/stub_SwapDir.cc \ @@ -2461,7 +2454,6 @@ tests/stub_StoreMeta.cc \ StoreMetaUnpacker.cc \ StoreSwapLogData.cc \ - String.cc \ StrList.h \ StrList.cc \ tests/stub_SwapDir.cc \ @@ -2538,7 +2530,6 @@ MemBuf.h \ Mem.h \ tests/stub_mem.cc \ - String.cc \ cache_cf.h \ YesNoNone.h \ $(SBUF_SOURCE) \ @@ -2582,7 +2573,6 @@ HttpRequestMethod.cc \ Mem.h \ tests/stub_mem.cc \ - String.cc \ tests/testHttpRequest.h \ tests/testHttpRequest.cc \ tests/testHttpRequestMethod.h \ @@ -2887,7 +2877,6 @@ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ - String.cc \ StrList.h \ StrList.cc \ SwapDir.cc \ @@ -2991,7 +2980,6 @@ Mem.h \ tests/stub_mem.cc \ MemBuf.cc \ - String.cc \ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ @@ -3124,7 +3112,6 @@ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ - String.cc \ tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ @@ -3305,7 +3292,6 @@ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ - String.cc \ StrList.h \ StrList.cc \ SwapDir.cc \ @@ -3561,7 +3547,6 @@ tests/stub_StoreMeta.cc \ StoreMetaUnpacker.cc \ StoreSwapLogData.cc \ - String.cc \ StrList.h \ StrList.cc \ tests/stub_SwapDir.cc \ @@ -3657,8 +3642,6 @@ tests/stub_store.cc \ tests/stub_store_stats.cc \ tests/stub_tools.cc \ - SquidString.h \ - String.cc \ tests/stub_wordlist.cc \ tests/stub_MemBuf.cc nodist_tests_testSBuf_SOURCES=$(TESTSOURCES) @@ -3697,7 +3680,6 @@ tests/stub_store_stats.cc \ tests/stub_tools.cc \ SquidString.h \ - String.cc \ tests/stub_wordlist.cc \ tests/stub_MemBuf.cc nodist_tests_testSBufList_SOURCES=$(TESTSOURCES) @@ -3723,7 +3705,6 @@ $(SBUF_SOURCE) \ SBufDetailedStats.h \ tests/stub_SBufDetailedStats.cc \ - String.cc \ ConfigParser.cc \ fatal.h \ tests/stub_fatal.cc \ @@ -3763,7 +3744,6 @@ tests/stub_MemBuf.cc \ StatHist.cc \ StatHist.h \ - String.cc \ tests/stub_cache_manager.cc \ tests/stub_comm.cc \ tests/stub_debug.cc \ @@ -3777,9 +3757,13 @@ tests/stub_pconn.cc \ tests/stub_stmem.cc \ repl_modules.h \ + $(SBUF_SOURCE) \ + SBufDetailedStats.h \ + tests/stub_SBufDetailedStats.cc \ tests/stub_store.cc \ tests/stub_store_stats.cc \ tools.h \ + tests/stub_time.cc \ tests/stub_tools.cc \ tests/testMain.cc \ tests/testStatHist.cc \ === modified file 'src/SBuf.cc' --- src/SBuf.cc 2013-12-18 17:53:43 +0000 +++ src/SBuf.cc 2013-12-19 07:56:42 +0000 @@ -117,16 +117,6 @@ ++stats.live; } -SBuf::SBuf(const String &S) - : store_(GetStorePrototype()), off_(0), len_(0) -{ - debugs(24, 8, id << " created from string"); - assign(S.rawBuf(), S.size()); - ++stats.alloc; - ++stats.allocFromString; - ++stats.live; -} - SBuf::SBuf(const std::string &s) : store_(GetStorePrototype()), off_(0), len_(0) { @@ -758,7 +748,7 @@ os << "SBuf stats:\nnumber of allocations: " << alloc << "\ncopy-allocations: " << allocCopy << - "\ncopy-allocations from SquidString: " << allocFromString << + "\ncopy-allocations from std::string: " << allocFromString << "\ncopy-allocations from C String: " << allocFromCString << "\nlive references: " << live << "\nno-copy assignments: " << assignFast << @@ -825,15 +815,6 @@ throw OutOfBoundsException(*this, pos, __FILE__, __LINE__); } -String -SBuf::toString() const -{ - String rv; - rv.limitInit(buf(), length()); - ++stats.copyOut; - return rv; -} - /** re-allocate the backing store of the SBuf. * * If there are contents in the SBuf, they will be copied over. === modified file 'src/SBuf.h' --- src/SBuf.h 2013-12-18 17:53:43 +0000 +++ src/SBuf.h 2013-12-19 07:56:42 +0000 @@ -32,7 +32,6 @@ #include "base/InstanceId.h" #include "MemBlob.h" #include "SBufExceptions.h" -#include "SquidString.h" #if HAVE_CLIMITS #include <climits> @@ -134,12 +133,6 @@ */ explicit SBuf(const char *S, size_type n = npos); - /** Constructor: import SquidString, copying contents. - * - * This method will be removed once SquidString has gone. - */ - explicit SBuf(const String &S); - /// Constructor: import std::string. Contents are copied. explicit SBuf(const std::string &s); @@ -313,7 +306,7 @@ /** exports a pointer to the SBuf internal storage. * \warning ACCESSING RAW STORAGE IS DANGEROUS! * - * Returns a ead-only pointer to SBuf's content. No terminating null + * Returns a read-only pointer to SBuf's content. No terminating null * character is appended (use c_str() for that). * The returned value points to an internal location whose contents * are guaranteed to remain unchanged only until the next call @@ -551,12 +544,6 @@ */ SBuf toUpper() const; - /** String export function - * converts the SBuf to a legacy String, by copy. - * \deprecated - */ - String toString() const; - /// std::string export function std::string toStdString() const { return std::string(buf(),length()); } === modified file 'src/Server.cc' --- src/Server.cc 2013-12-19 00:55:46 +0000 +++ src/Server.cc 2013-12-19 07:56:42 +0000 @@ -478,7 +478,7 @@ absUrl = NULL; hdrUrl = rep->header.getStr(hdr); - if (hdrUrl == NULL) { + if (!hdrUrl || !*hdrUrl) { return; } === modified file 'src/SquidString.h' --- src/SquidString.h 2013-12-20 05:55:43 +0000 +++ src/SquidString.h 2013-12-19 08:06:39 +0000 @@ -33,6 +33,8 @@ #ifndef SQUID_STRING_H #define SQUID_STRING_H +#include "SBuf.h" + #if HAVE_OSTREAM #include <ostream> #endif @@ -50,15 +52,24 @@ _SQUID_INLINE_ String(); String(char const *); String(String const &); - ~String(); - - typedef size_t size_type; //storage size intentionally unspecified - const static size_type npos = static_cast<size_type>(-1); + + explicit String(SBuf const &s) : buf_(s), defined_(s.length() > 0) {} + SBuf &toSBuf() const {return buf_;} + + typedef SBuf::size_type size_type; //storage size intentionally unspecified + const static size_type npos = SBuf::npos; String &operator =(char const *); String &operator =(String const &); + String &operator =(SBuf const &s) { + defined_=(s.length() > 0); // SBuf is always defined; estimating + buf_=s; + return *this; + } bool operator ==(String const &) const; + // {return defined() == s.defined() && buf_ == s.buf_;} bool operator !=(String const &) const; + // {return defined() != s.defined() || buf_ != s.buf_;} /** * Retrieve a single character in the string. @@ -109,25 +120,18 @@ _SQUID_INLINE_ void cut(size_type newLength); private: - void allocAndFill(const char *str, int len); - void allocBuffer(size_type sz); - void setBuffer(char *buf, size_type sz); - - bool defined() const {return buf_!=NULL;} - bool undefined() const {return !defined();} + bool defined() const {return defined_;} _SQUID_INLINE_ bool nilCmp(bool, bool, int &) const; - /* never reference these directly! */ - size_type size_; /* buffer size; 64K limit */ - - size_type len_; /* current length */ - - char *buf_; - - _SQUID_INLINE_ void set(char const *loc, char const ch); - _SQUID_INLINE_ void cutPointer(char const *loc); - + mutable SBuf buf_; + + // SquidString used to track whether buf_ was NULL or not + // and some code makes use of this property. + // Until that is all checked and defined()/undefined() erased + // we explicitly track whether SquidString would have had + // buf_ allocated. + mutable bool defined_; }; _SQUID_INLINE_ std::ostream & operator<<(std::ostream& os, String const &aString); === modified file 'src/StrList.cc' --- src/StrList.cc 2012-08-29 09:34:34 +0000 +++ src/StrList.cc 2013-12-10 12:34:23 +0000 @@ -113,7 +113,7 @@ if (!*pos) { *pos = str->termedBuf(); - if (!*pos) + if (!*pos || !**pos) return 0; } === modified file 'src/String.cc' --- src/String.cc 2012-10-04 09:14:06 +0000 +++ src/String.cc 2013-11-21 10:31:43 +0000 @@ -37,6 +37,7 @@ #include "mgr/Registration.h" #include "profiler/Profiler.h" #include "Store.h" +#include "SquidString.h" #if HAVE_LIMITS_H #include <limits.h> @@ -49,37 +50,10 @@ return size(); } -// low-level buffer allocation, -// does not free old buffer and does not adjust or look at len_ -void -String::allocBuffer(String::size_type sz) -{ - PROF_start(StringInitBuf); - assert (undefined()); - char *newBuffer = (char*)memAllocString(sz, &sz); - setBuffer(newBuffer, sz); - PROF_stop(StringInitBuf); -} - -// low-level buffer assignment -// does not free old buffer and does not adjust or look at len_ -void -String::setBuffer(char *aBuf, String::size_type aSize) -{ - assert(undefined()); - assert(aSize < 65536); - buf_ = aBuf; - size_ = aSize; -} - -String::String(char const *aString) : size_(0), len_(0), buf_(NULL) -{ - if (aString) - allocAndFill(aString, strlen(aString)); -#if DEBUGSTRINGS - - StringRegistry::Instance().add(this); -#endif +String::String(char const *aString) : + buf_(aString), + defined_(aString != NULL) +{ } String & @@ -92,9 +66,8 @@ String & String::operator =(String const &old) { - clean(); // TODO: optimize to avoid cleaning the buffer we can use - if (old.size() > 0) - allocAndFill(old.rawBuf(), old.size()); + buf_ = old.buf_; + defined_ = old.defined_; return *this; } @@ -121,31 +94,11 @@ String::limitInit(const char *str, int len) { clean(); // TODO: optimize to avoid cleaning the buffer we can use - allocAndFill(str, len); -} - -// Allocates the buffer to fit the supplied string and fills it. -// Does not clean. -void -String::allocAndFill(const char *str, int len) -{ - PROF_start(StringAllocAndFill); - assert(this && str); - allocBuffer(len + 1); - len_ = len; - memcpy(buf_, str, len); - buf_[len] = '\0'; - PROF_stop(StringAllocAndFill); -} - -String::String(String const &old) : size_(0), len_(0), buf_(NULL) -{ - if (old.size() > 0) - allocAndFill(old.rawBuf(), old.size()); -#if DEBUGSTRINGS - - StringRegistry::Instance().add(this); -#endif + append(str, len); +} + +String::String(String const &old) : buf_(old.buf_), defined_(old.defined_) +{ } void @@ -154,34 +107,23 @@ PROF_start(StringClean); assert(this); - /* TODO if mempools has already closed this will FAIL!! */ - if (defined()) - memFreeString(size_, buf_); - - len_ = 0; - - size_ = 0; - - buf_ = NULL; + buf_.clear(); + defined_=false; + PROF_stop(StringClean); } -String::~String() -{ - clean(); -#if DEBUGSTRINGS - - StringRegistry::Instance().remove(this); -#endif -} - void String::reset(char const *str) { PROF_start(StringReset); clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it - if (str) - allocAndFill(str, strlen(str)); + if (str) { + append(str); + // XXX: empty string "" sent to append means no change, + // but on reset / assignment it means set a defined empty string. + defined_=true; + } PROF_stop(StringReset); } @@ -192,26 +134,8 @@ assert(str && len >= 0); PROF_start(StringAppend); - if (len_ + len < size_) { - strncat(buf_, str, len); - len_ += len; - } else { - // Create a temporary string and absorb it later. - String snew; - assert(len_ + len < 65536); // otherwise snew.len_ overflows below - snew.len_ = len_ + len; - snew.allocBuffer(snew.len_ + 1); - - if (len_) - memcpy(snew.buf_, rawBuf(), len_); - - if (len) - memcpy(snew.buf_ + len_, str, len); - - snew.buf_[snew.len_] = '\0'; - - absorb(snew); - } + buf_.append(str, len); + defined_ = true; PROF_stop(StringAppend); } @@ -234,31 +158,24 @@ void String::append(String const &old) { - append(old.rawBuf(), old.len_); + append(old.rawBuf(), old.size()); } void String::absorb(String &old) { - clean(); - setBuffer(old.buf_, old.size_); - len_ = old.len_; - old.size_ = 0; - old.buf_ = NULL; - old.len_ = 0; + operator = (old); + old.clean(); } String String::substr(String::size_type from, String::size_type to) const { -// Must(from >= 0 && from < size()); Must(from < size()); Must(to > 0 && to <= size()); Must(to > from); - String rv; - rv.limitInit(rawBuf()+from,to-from); - return rv; + return String(buf_.substr(from, to-from)); } #if DEBUGSTRINGS @@ -442,7 +359,7 @@ const char * String::pos(char const *aString) const { - if (undefined()) + if (!defined()) return NULL; return strstr(termedBuf(), aString); } @@ -450,7 +367,7 @@ const char * String::pos(char const ch) const { - if (undefined()) + if (!defined()) return NULL; return strchr(termedBuf(), ch); } @@ -458,7 +375,7 @@ const char * String::rpos(char const ch) const { - if (undefined()) + if (!defined()) return NULL; return strrchr(termedBuf(), (ch)); } === modified file 'src/String.cci' --- src/String.cci 2013-11-23 00:58:42 +0000 +++ src/String.cci 2013-12-11 05:56:46 +0000 @@ -40,35 +40,36 @@ #endif /* INT_MAX */ #endif /* HAVE_STDINT_H */ -String::String() : size_(0), len_(0), buf_(NULL) +String::String() : buf_(), defined_(false) { -#if DEBUGSTRINGS - StringRegistry::Instance().add(this); -#endif } String::size_type String::size() const { - return len_; + return buf_.length(); } char const * String::rawBuf() const { - return buf_; + return termedBuf(); } char const * String::termedBuf() const { - return buf_; + // XXX: callers will probably try and write to the buffer, + // but SquidString never offered any more guarantee than SBuf + // does now about buffers existence. + // (this used to return NULL result on undefined) + return buf_.c_str(); } char String::operator [](unsigned int aPos) const { - assert(aPos < size_); + assert(aPos < size()); return buf_[aPos]; } @@ -94,11 +95,7 @@ int String::cmp(char const *aString) const { - int result = 0; - if (nilCmp(!size(), (!aString || !*aString), result)) - return result; - - return strcmp(termedBuf(), aString); + return buf_.cmp(SBuf(aString)); } int @@ -114,21 +111,13 @@ int String::cmp(String const &aString) const { - int result = 0; - if (nilCmp(!size(), !aString.size(), result)) - return result; - - return strcmp(termedBuf(), aString.termedBuf()); + return buf_.cmp(aString.buf_); } int String::caseCmp(char const *aString) const { - int result = 0; - if (nilCmp(!size(), (!aString || !*aString), result)) - return result; - - return strcasecmp(termedBuf(), aString); + return buf_.caseCmp(SBuf(aString)); } int @@ -144,44 +133,27 @@ int String::caseCmp(const String &str) const { - return caseCmp(str.rawBuf(),str.size()); -} - -void -String::set(char const *loc, char const ch) -{ - if (loc < buf_ || loc > (buf_ + size_) ) return; - - buf_[loc-buf_] = ch; + return buf_.caseCmp(str.buf_); } void String::cut(String::size_type newLength) { // size_type is size_t, unsigned. No need to check for newLength <0 - if (newLength > len_) return; + if (newLength > buf_.length()) return; - len_ = newLength; + buf_ = buf_.substr(0, newLength); // buf_ may be NULL on zero-length strings. - if (len_ == 0 && buf_ == NULL) return; - - buf_[newLength] = '\0'; -} - -void -String::cutPointer(char const *loc) -{ - if (loc < buf_ || loc > (buf_ + size_) ) return; - - len_ = loc-buf_; - buf_[len_] = '\0'; + if (buf_.length() == 0 && !defined()) return; + + buf_.setAt(newLength, '\0'); // terminate String. } std::ostream & operator<<(std::ostream& os, String const &aString) { - os.write(aString.rawBuf(),aString.size()); + os << aString.toSBuf(); return os; } === modified file 'src/acl/HttpHeaderData.cc' --- src/acl/HttpHeaderData.cc 2013-11-21 13:05:47 +0000 +++ src/acl/HttpHeaderData.cc 2013-12-19 08:07:16 +0000 @@ -76,8 +76,7 @@ return false; } - SBuf cvalue(value); - return regex_rule->match(cvalue.c_str()); + return regex_rule->match(value.termedBuf()); } wordlist * === modified file 'src/acl/ReplyHeaderStrategy.h' --- src/acl/ReplyHeaderStrategy.h 2013-10-25 00:13:46 +0000 +++ src/acl/ReplyHeaderStrategy.h 2013-12-11 05:29:21 +0000 @@ -67,7 +67,7 @@ { char const *theHeader = checklist->reply->header.getStr(header); - if (NULL == theHeader) + if (!theHeader || !*theHeader) return 0; return data->match(theHeader); === modified file 'src/acl/RequestHeaderStrategy.h' --- src/acl/RequestHeaderStrategy.h 2013-10-25 00:13:46 +0000 +++ src/acl/RequestHeaderStrategy.h 2013-12-11 05:29:38 +0000 @@ -67,7 +67,7 @@ { char const *theHeader = checklist->request->header.getStr(header); - if (NULL == theHeader) + if (!theHeader || !*theHeader) return 0; return data->match(theHeader); === modified file 'src/adaptation/Iterator.cc' --- src/adaptation/Iterator.cc 2013-12-05 11:04:45 +0000 +++ src/adaptation/Iterator.cc 2013-12-19 07:56:42 +0000 @@ -56,7 +56,7 @@ request = theCause; Must(request); Adaptation::History::Pointer ah = request->adaptHistory(true); - SBuf gid(theGroup->id); + SBuf gid(theGroup->id.toSBuf()); ah->recordAdaptationService(gid); } @@ -96,7 +96,7 @@ if (Adaptation::Config::needHistory) { Adaptation::History::Pointer ah = request->adaptHistory(true); - SBuf uid(thePlan.current()->cfg().key); + SBuf uid(thePlan.current()->cfg().key.toSBuf()); ah->recordAdaptationService(uid); } === modified file 'src/adaptation/ecap/ServiceRep.cc' --- src/adaptation/ecap/ServiceRep.cc 2013-12-05 11:04:45 +0000 +++ src/adaptation/ecap/ServiceRep.cc 2013-12-19 07:56:42 +0000 @@ -235,7 +235,7 @@ bool Adaptation::Ecap::ServiceRep::wantsUrl(const String &urlPath) const { Must(up()); - return theService->wantsUrl(urlPath.termedBuf()); + return theService->wantsUrl(urlPath); } Adaptation::Initiate * === modified file 'src/auth/UserRequest.cc' --- src/auth/UserRequest.cc 2013-12-06 14:59:47 +0000 +++ src/auth/UserRequest.cc 2013-12-19 07:56:42 +0000 @@ -302,6 +302,10 @@ proxy_auth = request->header.getStr(headertype); + // handle empty string results + if (!*proxy_auth) + proxy_auth = NULL; + /* * a note on proxy_auth logix here: * proxy_auth==NULL -> unauthenticated request || already === modified file 'src/auth/digest/UserRequest.cc' --- src/auth/digest/UserRequest.cc 2013-12-06 14:59:47 +0000 +++ src/auth/digest/UserRequest.cc 2013-12-19 07:56:42 +0000 @@ -146,7 +146,7 @@ if (last_broken_addr != request->client_addr) { debugs(29, DBG_IMPORTANT, "Digest POST bug detected from " << request->client_addr << " using '" << - (useragent ? useragent : "-") << + (useragent && *useragent ? useragent : "-") << "'. Please upgrade browser. See Bug #630 for details."); last_broken_addr = request->client_addr; === modified file 'src/cache_manager.cc' --- src/cache_manager.cc 2013-10-25 00:13:46 +0000 +++ src/cache_manager.cc 2013-12-11 03:56:15 +0000 @@ -148,7 +148,7 @@ Mgr::Action::Pointer CacheManager::createNamedAction(const char *actionName) { - Must(actionName); + Must(actionName && *actionName); Mgr::Command::Pointer cmd = new Mgr::Command; cmd->profile = findAction(actionName); === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2013-12-06 14:59:47 +0000 +++ src/client_side_request.cc 2013-12-19 07:56:42 +0000 @@ -604,7 +604,7 @@ // Require a Host: header. const char *host = http->request->header.getStr(HDR_HOST); - if (!host) { + if (!host || !*host) { // TODO: dump out the HTTP/1.1 error about missing host header. // otherwise this is fine, can't forge a header value when its not even set. debugs(85, 3, HERE << "validate skipped with no Host: header present."); @@ -1064,7 +1064,6 @@ HttpRequest *request = http->request; HttpHeader *req_hdr = &request->header; bool no_cache = false; - const char *str; request->imslen = -1; request->ims = req_hdr->getTime(HDR_IF_MODIFIED_SINCE); @@ -1090,7 +1089,8 @@ */ if (Config.onoff.ie_refresh) { if (http->flags.accel && request->flags.ims) { - if ((str = req_hdr->getStr(HDR_USER_AGENT))) { + const char *str = req_hdr->getStr(HDR_USER_AGENT); + if (str && *str) { if (strstr(str, "MSIE 5.01") != NULL) no_cache=true; else if (strstr(str, "MSIE 5.0") != NULL) === modified file 'src/esi/VarState.cc' --- src/esi/VarState.cc 2012-11-19 11:29:31 +0000 +++ src/esi/VarState.cc 2013-12-11 05:42:34 +0000 @@ -409,7 +409,7 @@ ESIVariableUserAgent::esiUserOs_t ESIVariableUserAgent::identifyOs(char const *s) const { - if (!s) + if (!s || !*s) return ESI_OS_OTHER; if (strstr (s, "Windows")) === modified file 'src/http.cc' --- src/http.cc 2013-11-23 05:21:34 +0000 +++ src/http.cc 2013-12-19 07:56:42 +0000 @@ -451,7 +451,7 @@ * continuous push replies. These are generally dynamic and * probably should not be cachable */ - if ((v = hdr->getStr(HDR_CONTENT_TYPE))) + if ((v = hdr->getStr(HDR_CONTENT_TYPE)) && *v) if (!strncasecmp(v, "multipart/x-mixed-replace", 25)) { debugs(22, 3, HERE << "NO because Content-Type:multipart/x-mixed-replace"); return 0; @@ -591,7 +591,6 @@ String vary, hdr; const char *pos = NULL; const char *item; - const char *value; int ilen; static String vstr; @@ -613,10 +612,9 @@ strListAdd(&vstr, name, ','); hdr = request->header.getByName(name); safe_free(name); - value = hdr.termedBuf(); - if (value) { - value = rfc1738_escape_part(value); + if (hdr.size()) { + const char *value = rfc1738_escape_part(hdr.termedBuf()); vstr.append("=\"", 2); vstr.append(value); vstr.append("\"", 1); @@ -638,10 +636,9 @@ strListAdd(&vstr, name, ','); hdr = request->header.getByName(name); safe_free(name); - value = hdr.termedBuf(); - if (value) { - value = rfc1738_escape_part(value); + if (hdr.size()) { + const char *value = rfc1738_escape_part(hdr.termedBuf()); vstr.append("=\"", 2); vstr.append(value); vstr.append("\"", 1); @@ -654,7 +651,7 @@ #endif debugs(11, 3, "httpMakeVaryMark: " << vstr); - return vstr.termedBuf(); + return vstr.size() ? vstr.termedBuf() : NULL; } void === modified file 'src/redirect.cc' --- src/redirect.cc 2013-11-23 00:58:42 +0000 +++ src/redirect.cc 2013-12-10 12:46:54 +0000 @@ -260,7 +260,7 @@ #endif if (!r->client_ident && http->request->extacl_user.size() > 0) { - r->client_ident = http->request->extacl_user.termedBuf(); + r->client_ident = (http->request->extacl_user.size() ? http->request->extacl_user.termedBuf() : NULL); debugs(61, 5, HERE << "acl-user=" << (r->client_ident?r->client_ident:"NULL")); } === modified file 'src/ssl/ErrorDetail.cc' --- src/ssl/ErrorDetail.cc 2013-11-23 00:58:42 +0000 +++ src/ssl/ErrorDetail.cc 2013-12-02 09:59:30 +0000 @@ -473,7 +473,7 @@ static char tmpBuffer[64]; // We can use the GetErrorName but using the detailEntry is faster, // so try it first. - const char *err = detailEntry.name.termedBuf(); + const char *err = (detailEntry.name.size() ? detailEntry.name.termedBuf() : NULL); // error details not loaded yet or not defined in error_details.txt, // try the GetErrorName... @@ -494,8 +494,8 @@ { if (error_no == SSL_ERROR_NONE) return "[No Error]"; - if (const char *err = detailEntry.descr.termedBuf()) - return err; + if (detailEntry.descr.size() > 0) + return detailEntry.descr.termedBuf(); return "[Not available]"; } @@ -554,7 +554,7 @@ int code_len = 0; if (ErrorDetailsManager::GetInstance().getErrorDetail(error_no, request, detailEntry)) - s = detailEntry.detail.termedBuf(); + s = (detailEntry.detail.size() ? detailEntry.detail.termedBuf() : NULL); if (!s) s = SslErrorDetailDefaultStr; === modified file 'src/ssl/ErrorDetailManager.cc' --- src/ssl/ErrorDetailManager.cc 2013-11-23 05:21:34 +0000 +++ src/ssl/ErrorDetailManager.cc 2013-12-19 07:56:42 +0000 @@ -133,7 +133,7 @@ errDetails = new ErrorDetailsList(); ErrorDetailFile detailTmpl(errDetails); if (detailTmpl.loadFor(request.getRaw())) { - if (detailTmpl.language()) { + if (detailTmpl.language() && *detailTmpl.language() != '\0') { debugs(83, 8, HERE << "Found details on disk for language " << detailTmpl.language()); errDetails->errLanguage = detailTmpl.language(); cacheDetails(errDetails); === modified file 'src/tests/testSBuf.cc' --- src/tests/testSBuf.cc 2013-12-18 17:53:43 +0000 +++ src/tests/testSBuf.cc 2013-12-19 07:56:42 +0000 @@ -106,13 +106,6 @@ CPPUNIT_ASSERT_EQUAL(s4,s3); } - // TEST: go via SquidString adapters. - { - String str(fox); - SBuf s1(str); - CPPUNIT_ASSERT_EQUAL(literal,s1); - } - // TEST: go via std::string adapter. { std::string str(fox); === modified file 'src/tests/testString.cc' --- src/tests/testString.cc 2013-10-25 00:13:46 +0000 +++ src/tests/testString.cc 2013-11-20 22:04:34 +0000 @@ -37,13 +37,13 @@ String left(""); String right; /* an empty string ("") is equal to a default string */ - CPPUNIT_ASSERT(!left.cmp(right)); - CPPUNIT_ASSERT(!left.cmp(NULL)); - CPPUNIT_ASSERT(!left.cmp(NULL, 1)); + CPPUNIT_ASSERT_EQUAL(0,left.cmp(right)); + CPPUNIT_ASSERT_EQUAL(0,left.cmp(NULL)); + CPPUNIT_ASSERT_EQUAL(0,left.cmp(NULL, 1)); /* reverse the order to catch corners */ - CPPUNIT_ASSERT(!right.cmp(left)); - CPPUNIT_ASSERT(!right.cmp("")); - CPPUNIT_ASSERT(!right.cmp("", 1)); + CPPUNIT_ASSERT_EQUAL(0,right.cmp(left)); + CPPUNIT_ASSERT_EQUAL(0,right.cmp("")); + CPPUNIT_ASSERT_EQUAL(0,right.cmp("", 1)); } void