Bug: Leaking configurable SSL error details. Trunk r11496 "Configurable SSL error details messages" correctly disabled collection of HTTP statistics for non-HTTP header fields, such as configurable SSL error details. However, it also incorrectly disabled deletion of those non-HTTP header fields. Configurable SSL error details are only created during [re]configuration time, so the leak went unnoticed since 2011-06-17. However, when annotations were added to non-HTTP header fields (r12413), the old bug resulted in a major leak for configurations that annotate transactions. Fortunately, that major leak was removed by r12779 "helperNotes to NotePairs" polishing, which stopped using HttpHeader for annotations. === modified file 'src/HttpHeader.cc' --- src/HttpHeader.cc 2012-11-26 18:54:43 +0000 +++ src/HttpHeader.cc 2013-05-10 21:50:56 +0000 @@ -421,71 +421,71 @@ // we do not really care, but the caller probably does assert(owner == other.owner); clean(); update(&other, NULL); // will update the mask as well len = other.len; } return *this; } void HttpHeader::clean() { HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; assert(owner > hoNone && owner < hoEnd); debugs(55, 7, "cleaning hdr: " << this << " owner: " << owner); PROF_start(HttpHeaderClean); + if (owner <= hoReply) { /* * An unfortunate bug. The entries array is initialized * such that count is set to zero. httpHeaderClean() seems to * be called both when 'hdr' is created, and destroyed. Thus, * we accumulate a large number of zero counts for 'hdr' before * it is ever used. Can't think of a good way to fix it, except * adding a state variable that indicates whether or not 'hdr' * has been used. As a hack, just never count zero-sized header * arrays. */ - - if (owner <= hoReply) { if (0 != entries.count) HttpHeaderStats[owner].hdrUCountDistr.count(entries.count); ++ HttpHeaderStats[owner].destroyedCount; HttpHeaderStats[owner].busyDestroyedCount += entries.count > 0; + } // if (owner <= hoReply) while ((e = getEntry(&pos))) { /* tmp hack to try to avoid coredumps */ if (e->id < 0 || e->id >= HDR_ENUM_END) { debugs(55, DBG_CRITICAL, "HttpHeader::clean BUG: entry[" << pos << "] is invalid (" << e->id << "). Ignored."); } else { + if (owner <= hoReply) HttpHeaderStats[owner].fieldTypeDistr.count(e->id); /* yes, this deletion leaves us in an inconsistent state */ delete e; } } - } // if (owner <= hoReply) entries.clean(); httpHeaderMaskInit(&mask, 0); len = 0; PROF_stop(HttpHeaderClean); } /* append entries (also see httpHeaderUpdate) */ void HttpHeader::append(const HttpHeader * src) { const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; assert(src); assert(src != this); debugs(55, 7, "appending hdr: " << this << " += " << src); while ((e = src->getEntry(&pos))) { addEntry(e->clone()); } }