From: Amos Jeffries Date: Tue, 23 May 2017 06:46:26 +0000 (+1200) Subject: Replace String with SBuf for storage of header names in HttpHeaderEntry X-Git-Tag: M-staged-PR71~169 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5f1851770d972a9c87c9189d9b5927abb1877e3;p=thirdparty%2Fsquid.git Replace String with SBuf for storage of header names in HttpHeaderEntry In the process we gain SBuf methods for delByName and hasNamed. Deprecating the char* versions. --- diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index e1b3b584dc..d40146221f 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -9,6 +9,7 @@ /* DEBUG: section 55 HTTP Header */ #include "squid.h" +#include "base/CharacterSet.h" #include "base/EnumIterator.h" #include "base64.h" #include "globals.h" @@ -248,9 +249,8 @@ HttpHeader::needUpdate(HttpHeader const *fresh) const if (!e || skipUpdateHeader(e->id)) continue; String value; - const char *name = e->name.termedBuf(); - if (!hasNamed(name, strlen(name), &value) || - (value != fresh->getByName(name))) + if (!hasNamed(e->name, &value) || + (value != fresh->getByName(e->name))) return true; } return false; @@ -301,7 +301,7 @@ HttpHeader::update(HttpHeader const *fresh) if (e->id != Http::HdrType::OTHER) delById(e->id); else - delByName(e->name.termedBuf()); + delByName(e->name); } pos = HttpHeaderInitPos; @@ -492,7 +492,11 @@ HttpHeader::parse(const char *header_start, size_t hdrLen) return 0; } - if (e->id == Http::HdrType::OTHER && stringHasWhitespace(e->name.termedBuf())) { + /* AYJ 2017-05-23: I suspect we need to change this whitespace check to conform to the + updated WSP character set in RFC 7230/7231. For now I left it as the + characters in w_space which the previous code was using. */ + static CharacterSet wsp = (CharacterSet::WSP + CharacterSet::CR + CharacterSet::LF); + if (e->id == Http::HdrType::OTHER && e->name.findFirstOf(wsp) != SBuf::npos) { debugs(55, warnOnError, "WARNING: found whitespace in HTTP header name {" << getStringPrefix(field_start, field_end-field_start) << "}"); @@ -568,7 +572,7 @@ HttpHeader::packInto(Packable * p, bool mask_sensitive_info) const break; } if (maskThisEntry) { - p->append(e->name.rawBuf(), e->name.size()); + p->append(e->name.rawContent(), e->name.length()); p->append(": ** NOT DISPLAYED **\r\n", 23); } else { e->packInto(p); @@ -645,19 +649,15 @@ HttpHeader::findLastEntry(Http::HdrType id) const return nullptr; /* not reached */ } -/* - * deletes all fields with a given name if any, returns #fields deleted; - */ int -HttpHeader::delByName(const char *name) +HttpHeader::delByName(const SBuf &name) { int count = 0; HttpHeaderPos pos = HttpHeaderInitPos; - HttpHeaderEntry *e; httpHeaderMaskInit(&mask, 0); /* temporal inconsistency */ debugs(55, 9, "deleting '" << name << "' fields in hdr " << this); - while ((e = getEntry(&pos))) { + while (const HttpHeaderEntry *e = getEntry(&pos)) { if (!e->name.caseCmp(name)) delAt(pos, count); else @@ -704,7 +704,7 @@ HttpHeader::delAt(HttpHeaderPos pos, int &headers_deleted) e = static_cast(entries[pos]); entries[pos] = NULL; /* decrement header length, allow for ": " and crlf */ - len -= e->name.size() + 2 + e->value.size() + 2; + len -= e->name.length() + 2 + e->value.size() + 2; assert(len >= 0); delete e; ++headers_deleted; @@ -743,7 +743,7 @@ HttpHeader::addEntry(HttpHeaderEntry * e) { assert(e); assert(any_HdrType_enum_value(e->id)); - assert(e->name.size()); + assert(e->name.length()); debugs(55, 7, this << " adding entry: " << e->id << " at " << entries.size()); @@ -758,7 +758,7 @@ HttpHeader::addEntry(HttpHeaderEntry * e) entries.push_back(e); /* increment header length, allow for ": " and crlf */ - len += e->name.size() + 2 + e->value.size() + 2; + len += e->name.length() + 2 + e->value.size() + 2; } /* inserts an entry; @@ -782,7 +782,7 @@ HttpHeader::insertEntry(HttpHeaderEntry * e) entries.insert(entries.begin(),e); /* increment header length, allow for ": " and crlf */ - len += e->name.size() + 2 + e->value.size() + 2; + len += e->name.length() + 2 + e->value.size() + 2; } bool @@ -911,7 +911,7 @@ HttpHeader::getByIdIfPresent(Http::HdrType id, String *result) const } bool -HttpHeader::hasNamed(const char *name, int namelen, String *result) const +HttpHeader::hasNamed(const char *name, unsigned int namelen, String *result) const { Http::HdrType id; HttpHeaderPos pos = HttpHeaderInitPos; @@ -930,7 +930,7 @@ HttpHeader::hasNamed(const char *name, int namelen, String *result) const /* Sorry, an unknown header name. Do linear search */ bool found = false; while ((e = getEntry(&pos))) { - if (e->id == Http::HdrType::OTHER && e->name.size() == static_cast(namelen) && e->name.caseCmp(name, namelen) == 0) { + if (e->id == Http::HdrType::OTHER && e->name.length() == namelen && e->name.caseCmp(name, namelen) == 0) { found = true; if (!result) break; @@ -1038,7 +1038,7 @@ HttpHeader::putInt(Http::HdrType id, int number) assert(any_registered_header(id)); assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt); /* must be of an appropriate type */ assert(number >= 0); - addEntry(new HttpHeaderEntry(id, NULL, xitoa(number))); + addEntry(new HttpHeaderEntry(id, SBuf(), xitoa(number))); } void @@ -1047,7 +1047,7 @@ HttpHeader::putInt64(Http::HdrType id, int64_t number) assert(any_registered_header(id)); assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftInt64); /* must be of an appropriate type */ assert(number >= 0); - addEntry(new HttpHeaderEntry(id, NULL, xint64toa(number))); + addEntry(new HttpHeaderEntry(id, SBuf(), xint64toa(number))); } void @@ -1056,7 +1056,7 @@ HttpHeader::putTime(Http::HdrType id, time_t htime) assert(any_registered_header(id)); assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftDate_1123); /* must be of an appropriate type */ assert(htime >= 0); - addEntry(new HttpHeaderEntry(id, NULL, mkrfc1123(htime))); + addEntry(new HttpHeaderEntry(id, SBuf(), mkrfc1123(htime))); } void @@ -1065,7 +1065,7 @@ HttpHeader::putStr(Http::HdrType id, const char *str) assert(any_registered_header(id)); assert(Http::HeaderLookupTable.lookup(id).type == Http::HdrFieldType::ftStr); /* must be of an appropriate type */ assert(str); - addEntry(new HttpHeaderEntry(id, NULL, str)); + addEntry(new HttpHeaderEntry(id, SBuf(), str)); } void @@ -1086,7 +1086,7 @@ HttpHeader::putCc(const HttpHdrCc * cc) mb.init(); cc->packInto(&mb); /* put */ - addEntry(new HttpHeaderEntry(Http::HdrType::CACHE_CONTROL, NULL, mb.buf)); + addEntry(new HttpHeaderEntry(Http::HdrType::CACHE_CONTROL, SBuf(), mb.buf)); /* cleanup */ mb.clean(); } @@ -1102,7 +1102,7 @@ HttpHeader::putContRange(const HttpHdrContRange * cr) mb.init(); httpHdrContRangePackInto(cr, &mb); /* put */ - addEntry(new HttpHeaderEntry(Http::HdrType::CONTENT_RANGE, NULL, mb.buf)); + addEntry(new HttpHeaderEntry(Http::HdrType::CONTENT_RANGE, SBuf(), mb.buf)); /* cleanup */ mb.clean(); } @@ -1118,7 +1118,7 @@ HttpHeader::putRange(const HttpHdrRange * range) mb.init(); range->packInto(&mb); /* put */ - addEntry(new HttpHeaderEntry(Http::HdrType::RANGE, NULL, mb.buf)); + addEntry(new HttpHeaderEntry(Http::HdrType::RANGE, SBuf(), mb.buf)); /* cleanup */ mb.clean(); } @@ -1134,7 +1134,7 @@ HttpHeader::putSc(HttpHdrSc *sc) mb.init(); sc->packInto(&mb); /* put */ - addEntry(new HttpHeaderEntry(Http::HdrType::SURROGATE_CONTROL, NULL, mb.buf)); + addEntry(new HttpHeaderEntry(Http::HdrType::SURROGATE_CONTROL, SBuf(), mb.buf)); /* cleanup */ mb.clean(); } @@ -1153,7 +1153,7 @@ HttpHeader::putExt(const char *name, const char *value) { assert(name && value); debugs(55, 8, this << " adds ext entry " << name << " : " << value); - addEntry(new HttpHeaderEntry(Http::HdrType::OTHER, name, value)); + addEntry(new HttpHeaderEntry(Http::HdrType::OTHER, SBuf(name), value)); } int @@ -1397,7 +1397,7 @@ HttpHeader::getTimeOrTag(Http::HdrType id) const * HttpHeaderEntry */ -HttpHeaderEntry::HttpHeaderEntry(Http::HdrType anId, const char *aName, const char *aValue) +HttpHeaderEntry::HttpHeaderEntry(Http::HdrType anId, const SBuf &aName, const char *aValue) { assert(any_HdrType_enum_value(anId)); id = anId; @@ -1469,7 +1469,7 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end) Http::HdrType id = Http::HeaderLookupTable.lookup(field_start,name_len).id; debugs(55, 9, "got hdr-id=" << id); - String name; + SBuf theName; String value; @@ -1478,9 +1478,9 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end) /* set field name */ if (id == Http::HdrType::OTHER) - name.limitInit(field_start, name_len); + theName.append(field_start, name_len); else - name = Http::HeaderLookupTable.lookup(id).name; + theName = Http::HeaderLookupTable.lookup(id).name; /* trim field value */ while (value_start < field_end && xisspace(*value_start)) @@ -1491,11 +1491,7 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end) if (field_end - value_start > 65534) { /* String must be LESS THAN 64K and it adds a terminating NULL */ - debugs(55, DBG_IMPORTANT, "WARNING: ignoring '" << name << "' header of " << (field_end - value_start) << " bytes"); - - if (id == Http::HdrType::OTHER) - name.clean(); - + debugs(55, DBG_IMPORTANT, "WARNING: ignoring '" << theName << "' header of " << (field_end - value_start) << " bytes"); return NULL; } @@ -1505,22 +1501,22 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end) if (id != Http::HdrType::BAD_HDR) ++ headerStatsTable[id].seenCount; - debugs(55, 9, "parsed HttpHeaderEntry: '" << name << ": " << value << "'"); + debugs(55, 9, "parsed HttpHeaderEntry: '" << theName << ": " << value << "'"); - return new HttpHeaderEntry(id, name.termedBuf(), value.termedBuf()); + return new HttpHeaderEntry(id, theName, value.termedBuf()); } HttpHeaderEntry * HttpHeaderEntry::clone() const { - return new HttpHeaderEntry(id, name.termedBuf(), value.termedBuf()); + return new HttpHeaderEntry(id, name, value.termedBuf()); } void HttpHeaderEntry::packInto(Packable * p) const { assert(p); - p->append(name.rawBuf(), name.size()); + p->append(name.rawContent(), name.length()); p->append(": ", 2); p->append(value.rawBuf(), value.size()); p->append("\r\n", 2); @@ -1751,7 +1747,7 @@ HttpHeader::removeConnectionHeaderEntries() int headers_deleted = 0; while ((e = getEntry(&pos))) { - if (strListIsMember(&strConnection, e->name.termedBuf(), ',')) + if (strListIsMember(&strConnection, e->name, ',')) delAt(pos, headers_deleted); } if (headers_deleted) diff --git a/src/HttpHeader.h b/src/HttpHeader.h index 6947c728be..4f7ddf6a7c 100644 --- a/src/HttpHeader.h +++ b/src/HttpHeader.h @@ -52,7 +52,7 @@ class HttpHeaderEntry MEMPROXY_CLASS(HttpHeaderEntry); public: - HttpHeaderEntry(Http::HdrType id, const char *name, const char *value); + HttpHeaderEntry(Http::HdrType id, const SBuf &name, const char *value); ~HttpHeaderEntry(); static HttpHeaderEntry *parse(const char *field_start, const char *field_end); HttpHeaderEntry *clone() const; @@ -61,7 +61,7 @@ public: int64_t getInt64() const; Http::HdrType id; - String name; + SBuf name; String value; }; @@ -93,7 +93,11 @@ public: void packInto(Packable * p, bool mask_sensitive_info=false) const; HttpHeaderEntry *getEntry(HttpHeaderPos * pos) const; HttpHeaderEntry *findEntry(Http::HdrType id) const; - int delByName(const char *name); + /// deletes all fields with a given name, if any. + /// \return #fields deleted + int delByName(const SBuf &name); + /// \deprecated use SBuf method instead. performance regression: reallocates + int delByName(const char *name) { return delByName(SBuf(name)); } int delById(Http::HdrType id); void delAt(HttpHeaderPos pos, int &headers_deleted); void refreshMask(); @@ -112,7 +116,8 @@ public: /// returns true iff a [possibly empty] named field is there /// when returning true, also sets the `value` parameter (if it is not nil) bool hasNamed(const SBuf &s, String *value = 0) const; - bool hasNamed(const char *name, int namelen, String *value = 0) const; + /// \deprecated use SBuf method instead. + bool hasNamed(const char *name, unsigned int namelen, String *value = 0) const; String getByNameListMember(const char *name, const char *member, const char separator) const; String getListMember(Http::HdrType id, const char *member, const char separator) const; int has(Http::HdrType id) const; diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc index fba8a45268..c1669042e9 100644 --- a/src/HttpHeaderTools.cc +++ b/src/HttpHeaderTools.cc @@ -87,7 +87,7 @@ httpHeaderAddContRange(HttpHeader * hdr, HttpHdrRangeSpec spec, int64_t ent_len) * \note if no Connection header exists we may check the Proxy-Connection header */ bool -httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive) +httpHeaderHasConnDir(const HttpHeader * hdr, const SBuf &directive) { String list; @@ -456,7 +456,8 @@ HeaderManglers::find(const HttpHeaderEntry &e) const if (e.id == Http::HdrType::OTHER) { // does it have an ACL list configured? // Optimize: use a name type that we do not need to convert to here - const ManglersByName::const_iterator i = custom.find(e.name.termedBuf()); + SBuf tmp(e.name); // XXX: performance regression. c_str() reallocates + const ManglersByName::const_iterator i = custom.find(tmp.c_str()); if (i != custom.end()) return &i->second; } @@ -494,8 +495,7 @@ httpHdrAdd(HttpHeader *heads, HttpRequest *request, const AccessLogEntryPointer if (!fieldValue || fieldValue[0] == '\0') fieldValue = "-"; - HttpHeaderEntry *e = new HttpHeaderEntry(hwa->fieldId, hwa->fieldName.c_str(), - fieldValue); + HttpHeaderEntry *e = new HttpHeaderEntry(hwa->fieldId, SBuf(hwa->fieldName), fieldValue); heads->addEntry(e); } } diff --git a/src/HttpHeaderTools.h b/src/HttpHeaderTools.h index 23385a3d66..53aa0ebfdf 100644 --- a/src/HttpHeaderTools.h +++ b/src/HttpHeaderTools.h @@ -12,6 +12,7 @@ #include "acl/forward.h" #include "format/Format.h" #include "HttpHeader.h" +#include "sbuf/forward.h" #include #include @@ -25,7 +26,6 @@ class HeaderWithAcl; class HttpHeader; class HttpRequest; class StoreEntry; -class String; typedef std::list HeaderWithAclList; @@ -125,7 +125,7 @@ public: /// \return true if and only if no problems were found. bool httpHeaderParseOffset(const char *start, int64_t *offPtr, char **endPtr = nullptr); -bool httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive); +bool httpHeaderHasConnDir(const HttpHeader * hdr, const SBuf &directive); int httpHeaderParseInt(const char *start, int *val); void httpHeaderPutStrf(HttpHeader * hdr, Http::HdrType id, const char *fmt,...) PRINTF_FORMAT_ARG3; diff --git a/src/HttpReply.cc b/src/HttpReply.cc index c715d0708f..2d69207be0 100644 --- a/src/HttpReply.cc +++ b/src/HttpReply.cc @@ -563,7 +563,7 @@ void HttpReply::removeStaleWarnings() header.delById(Http::HdrType::WARNING); if (newWarning.size()) { // some warnings left HttpHeaderEntry *const e = - new HttpHeaderEntry(Http::HdrType::WARNING, NULL, newWarning.termedBuf()); + new HttpHeaderEntry(Http::HdrType::WARNING, SBuf(), newWarning.termedBuf()); header.addEntry(e); } } diff --git a/src/StrList.cc b/src/StrList.cc index 95d703f849..f03880ae6a 100644 --- a/src/StrList.cc +++ b/src/StrList.cc @@ -10,6 +10,7 @@ #include "squid.h" #include "base/TextException.h" +#include "sbuf/SBuf.h" #include "SquidString.h" #include "StrList.h" @@ -33,17 +34,16 @@ strListAdd(String * str, const char *item, char del) /** returns true iff "m" is a member of the list */ int -strListIsMember(const String * list, const char *m, char del) +strListIsMember(const String * list, const SBuf &m, char del) { const char *pos = NULL; const char *item; int ilen = 0; - int mlen; - assert(list && m); - mlen = strlen(m); + assert(list); + int mlen = m.plength(); while (strListGetItem(list, del, &item, &ilen, &pos)) { - if (mlen == ilen && !strncasecmp(item, m, ilen)) + if (mlen == ilen && m.caseCmp(item, ilen) == 0) return 1; } return 0; diff --git a/src/StrList.h b/src/StrList.h index fa1af23afc..3e0da7f803 100644 --- a/src/StrList.h +++ b/src/StrList.h @@ -11,10 +11,12 @@ #ifndef SQUID_STRLIST_H_ #define SQUID_STRLIST_H_ +#include "sbuf/forward.h" + class String; void strListAdd(String * str, const char *item, char del); -int strListIsMember(const String * str, const char *item, char del); +int strListIsMember(const String * str, const SBuf &item, char del); int strListIsSubstr(const String * list, const char *s, char del); int strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos); diff --git a/src/adaptation/ecap/MessageRep.cc b/src/adaptation/ecap/MessageRep.cc index fdd890c9c9..360c168493 100644 --- a/src/adaptation/ecap/MessageRep.cc +++ b/src/adaptation/ecap/MessageRep.cc @@ -53,7 +53,7 @@ void Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value) { const Http::HdrType squidId = TranslateHeaderId(name); // Http::HdrType::OTHER OK - HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(), + HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image(), value.toString().c_str()); theHeader.addEntry(e); diff --git a/src/adaptation/icap/ModXact.cc b/src/adaptation/icap/ModXact.cc index b182b1b6c3..acb271b545 100644 --- a/src/adaptation/icap/ModXact.cc +++ b/src/adaptation/icap/ModXact.cc @@ -797,7 +797,8 @@ void Adaptation::Icap::ModXact::parseIcapHead() trailerParser = new TrailerParser; } - if (httpHeaderHasConnDir(&icapReply->header, "close")) { + static SBuf close("close", 5); + if (httpHeaderHasConnDir(&icapReply->header, close)) { debugs(93, 5, HERE << "found connection close"); reuseConnection = false; } diff --git a/src/adaptation/icap/OptXact.cc b/src/adaptation/icap/OptXact.cc index 7ea7465a71..afa6e4b604 100644 --- a/src/adaptation/icap/OptXact.cc +++ b/src/adaptation/icap/OptXact.cc @@ -111,7 +111,8 @@ bool Adaptation::Icap::OptXact::parseResponse() if (!parseHttpMsg(r.getRaw())) // throws on errors return false; - if (httpHeaderHasConnDir(&r->header, "close")) + static SBuf close("close", 5); + if (httpHeaderHasConnDir(&r->header, close)) reuseConnection = false; icapReply = r; diff --git a/src/format/Format.cc b/src/format/Format.cc index 343d8d5db4..42ad1a0c77 100644 --- a/src/format/Format.cc +++ b/src/format/Format.cc @@ -747,7 +747,7 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS if (al->icap.request) { HttpHeaderPos pos = HttpHeaderInitPos; while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) { - sb.append(StringToSBuf(e->name)); + sb.append(e->name); sb.append(": "); sb.append(StringToSBuf(e->value)); sb.append("\r\n"); @@ -777,7 +777,7 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS if (al->icap.reply) { HttpHeaderPos pos = HttpHeaderInitPos; while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) { - sb.append(StringToSBuf(e->name)); + sb.append(e->name); sb.append(": "); sb.append(StringToSBuf(e->value)); sb.append("\r\n"); diff --git a/src/http.cc b/src/http.cc index c193a5de89..c19971a323 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1041,7 +1041,8 @@ HttpStateData::statusIfComplete() const /** \par * If the reply wants to close the connection, it takes precedence */ - if (httpHeaderHasConnDir(&rep->header, "close")) + static SBuf close("close", 5); + if (httpHeaderHasConnDir(&rep->header, close)) return COMPLETE_NONPERSISTENT_MSG; /** \par @@ -1773,7 +1774,7 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request, // Add our own If-None-Match field if the cached entry has a strong ETag. // copyOneHeaderFromClientsideRequestToUpstreamRequest() adds client ones. if (request->etag.size() > 0) { - hdr_out->addEntry(new HttpHeaderEntry(Http::HdrType::IF_NONE_MATCH, NULL, + hdr_out->addEntry(new HttpHeaderEntry(Http::HdrType::IF_NONE_MATCH, SBuf(), request->etag.termedBuf())); } @@ -2099,8 +2100,7 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, co /** \par default. * pass on all other header fields * which are NOT listed by the special Connection: header. */ - - if (strConnection.size()>0 && strListIsMember(&strConnection, e->name.termedBuf(), ',')) { + if (strConnection.size()>0 && strListIsMember(&strConnection, e->name, ',')) { debugs(11, 2, "'" << e->name << "' header cropped by Connection: definition"); return; } diff --git a/src/http/Message.cc b/src/http/Message.cc index b5e699b511..3a1ac1baeb 100644 --- a/src/http/Message.cc +++ b/src/http/Message.cc @@ -261,10 +261,12 @@ Http::Message::persistent() const * for modern versions of HTTP: persistent unless there is * a "Connection: close" header. */ - return !httpHeaderHasConnDir(&header, "close"); + static SBuf close("close", 5); + return !httpHeaderHasConnDir(&header, close); } else { /* for old versions of HTTP: persistent if has "keep-alive" */ - return httpHeaderHasConnDir(&header, "keep-alive"); + static SBuf keepAlive("keep-alive", 10); + return httpHeaderHasConnDir(&header, keepAlive); } } diff --git a/src/store.cc b/src/store.cc index 2220725be8..0804d8a972 100644 --- a/src/store.cc +++ b/src/store.cc @@ -2004,8 +2004,10 @@ bool StoreEntry::hasOneOfEtags(const String &reqETags, const bool allowWeakMatch) const { const ETag repETag = getReply()->header.getETag(Http::HdrType::ETAG); - if (!repETag.str) - return strListIsMember(&reqETags, "*", ','); + if (!repETag.str) { + static SBuf asterisk("*", 1); + return strListIsMember(&reqETags, asterisk, ','); + } bool matched = false; const char *pos = NULL;