]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/http/ContentLengthInterpreter.cc
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 55 HTTP Header */
12 #include "base/CharacterSet.h"
14 #include "http/ContentLengthInterpreter.h"
15 #include "http/one/Parser.h"
16 #include "HttpHeaderTools.h"
17 #include "SquidConfig.h"
18 #include "SquidString.h"
21 Http::ContentLengthInterpreter::ContentLengthInterpreter(const int aDebugLevel
):
23 headerWideProblem(nullptr),
24 debugLevel(aDebugLevel
),
26 needsSanitizing(false),
31 /// checks whether all characters after the Content-Length are allowed
33 Http::ContentLengthInterpreter::goodSuffix(const char *suffix
, const char * const end
) const
35 // optimize for the common case that does not need delimiters
39 for (const CharacterSet
&delimiters
= Http::One::Parser::DelimiterCharacters();
40 suffix
< end
; ++suffix
) {
41 if (!delimiters
[*suffix
])
44 // needsSanitizing = true; // TODO: Always remove trailing whitespace?
45 return true; // including empty suffix
48 /// handles a single-token Content-Length value
49 /// rawValue null-termination requirements are those of httpHeaderParseOffset()
51 Http::ContentLengthInterpreter::checkValue(const char *rawValue
, const int valueSize
)
55 int64_t latestValue
= -1;
56 char *suffix
= nullptr;
57 // TODO: Handle malformed values with leading signs (e.g., "-0" or "+1").
58 if (!httpHeaderParseOffset(rawValue
, &latestValue
, &suffix
)) {
59 debugs(55, DBG_IMPORTANT
, "WARNING: Malformed" << Raw("Content-Length", rawValue
, valueSize
));
64 if (latestValue
< 0) {
65 debugs(55, debugLevel
, "WARNING: Negative" << Raw("Content-Length", rawValue
, valueSize
));
70 // check for garbage after the number
71 if (!goodSuffix(suffix
, rawValue
+ valueSize
)) {
72 debugs(55, debugLevel
, "WARNING: Trailing garbage in" << Raw("Content-Length", rawValue
, valueSize
));
78 /* we have found at least two, possibly identical values */
80 needsSanitizing
= true; // replace identical values with a single value
82 const bool conflicting
= value
!= latestValue
;
84 headerWideProblem
= "Conflicting"; // overwrite any lesser problem
85 else if (!headerWideProblem
) // preserve a possibly worse problem
86 headerWideProblem
= "Duplicate";
88 // with relaxed_header_parser, identical values are permitted
89 sawBad
= !Config
.onoff
.relaxed_header_parser
|| conflicting
;
90 return false; // conflicting or duplicate
98 /// handles Content-Length: a, b, c
100 Http::ContentLengthInterpreter::checkList(const String
&list
)
104 if (!Config
.onoff
.relaxed_header_parser
) {
105 debugs(55, debugLevel
, "WARNING: List-like" << Raw("Content-Length", list
.rawBuf(), list
.size()));
110 needsSanitizing
= true; // remove extra commas (at least)
112 const char *pos
= nullptr;
113 const char *item
= nullptr;;
115 while (strListGetItem(&list
, ',', &item
, &ilen
, &pos
)) {
116 if (!checkValue(item
, ilen
) && sawBad
)
118 // keep going after a duplicate value to find conflicting ones
120 return false; // no need to keep this list field; it will be sanitized away
124 Http::ContentLengthInterpreter::checkField(const String
&rawValue
)
127 return false; // one rotten apple is enough to spoil all of them
129 // TODO: Optimize by always parsing the first integer first.
130 return rawValue
.pos(',') ?
131 checkList(rawValue
) :
132 checkValue(rawValue
.rawBuf(), rawValue
.size());