ContentLengthInterpreter.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 /* DEBUG: section 55 HTTP Header */
10 
11 #include "squid.h"
12 #include "base/CharacterSet.h"
13 #include "Debug.h"
15 #include "http/one/Parser.h"
16 #include "HttpHeaderTools.h"
17 #include "SquidConfig.h"
18 #include "SquidString.h"
19 #include "StrList.h"
20 
22  value(-1),
23  headerWideProblem(nullptr),
24  debugLevel(Config.onoff.relaxed_header_parser <= 0 ? DBG_IMPORTANT : 2),
25  sawBad(false),
26  needsSanitizing(false),
27  sawGood(false),
28  prohibitedAndIgnored_(nullptr)
29 {
30 }
31 
33 bool
34 Http::ContentLengthInterpreter::goodSuffix(const char *suffix, const char * const end) const
35 {
36  // optimize for the common case that does not need delimiters
37  if (suffix == end)
38  return true;
39 
40  for (const CharacterSet &delimiters = Http::One::Parser::DelimiterCharacters();
41  suffix < end; ++suffix) {
42  if (!delimiters[*suffix])
43  return false;
44  }
45  // needsSanitizing = true; // TODO: Always remove trailing whitespace?
46  return true; // including empty suffix
47 }
48 
51 bool
52 Http::ContentLengthInterpreter::checkValue(const char *rawValue, const int valueSize)
53 {
54  Must(!sawBad);
55 
56  int64_t latestValue = -1;
57  char *suffix = nullptr;
58  // TODO: Handle malformed values with leading signs (e.g., "-0" or "+1").
59  if (!httpHeaderParseOffset(rawValue, &latestValue, &suffix)) {
60  debugs(55, DBG_IMPORTANT, "WARNING: Malformed" << Raw("Content-Length", rawValue, valueSize));
61  sawBad = true;
62  return false;
63  }
64 
65  if (latestValue < 0) {
66  debugs(55, debugLevel, "WARNING: Negative" << Raw("Content-Length", rawValue, valueSize));
67  sawBad = true;
68  return false;
69  }
70 
71  // check for garbage after the number
72  if (!goodSuffix(suffix, rawValue + valueSize)) {
73  debugs(55, debugLevel, "WARNING: Trailing garbage in" << Raw("Content-Length", rawValue, valueSize));
74  sawBad = true;
75  return false;
76  }
77 
78  if (sawGood) {
79  /* we have found at least two, possibly identical values */
80 
81  needsSanitizing = true; // replace identical values with a single value
82 
83  const bool conflicting = value != latestValue;
84  if (conflicting)
85  headerWideProblem = "Conflicting"; // overwrite any lesser problem
86  else if (!headerWideProblem) // preserve a possibly worse problem
87  headerWideProblem = "Duplicate";
88 
89  // with relaxed_header_parser, identical values are permitted
90  sawBad = !Config.onoff.relaxed_header_parser || conflicting;
91  return false; // conflicting or duplicate
92  }
93 
94  sawGood = true;
95  value = latestValue;
96  return true;
97 }
98 
100 bool
102 {
103  Must(!sawBad);
104 
106  debugs(55, debugLevel, "WARNING: List-like" << Raw("Content-Length", list.rawBuf(), list.size()));
107  sawBad = true;
108  return false;
109  }
110 
111  needsSanitizing = true; // remove extra commas (at least)
112 
113  const char *pos = nullptr;
114  const char *item = nullptr;;
115  int ilen = -1;
116  while (strListGetItem(&list, ',', &item, &ilen, &pos)) {
117  if (!checkValue(item, ilen) && sawBad)
118  break;
119  // keep going after a duplicate value to find conflicting ones
120  }
121  return false; // no need to keep this list field; it will be sanitized away
122 }
123 
124 bool
126 {
127  if (sawBad)
128  return false; // one rotten apple is enough to spoil all of them
129 
130  // TODO: Optimize by always parsing the first integer first.
131  return rawValue.pos(',') ?
132  checkList(rawValue) :
133  checkValue(rawValue.rawBuf(), rawValue.size());
134 }
135 
bool httpHeaderParseOffset(const char *start, int64_t *value, char **endPtr)
int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
Definition: StrList.cc:77
static const CharacterSet & DelimiterCharacters()
Definition: Parser.cc:58
bool goodSuffix(const char *suffix, const char *const end) const
checks whether all characters after the Content-Length are allowed
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
const char * pos(char const *aString) const
Definition: String.cc:498
size_type size() const
Definition: SquidString.h:72
bool checkList(const String &list)
handles Content-Length: a, b, c
int relaxed_header_parser
Definition: SquidConfig.h:318
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
#define DBG_IMPORTANT
Definition: Debug.h:46
char const * rawBuf() const
Definition: SquidString.h:85
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:17
struct SquidConfig::@112 onoff
bool checkValue(const char *start, const int size)
Definition: Debug.h:184
class SquidConfig Config
Definition: SquidConfig.cc:12
#define false
Definition: GnuRegex.c:233

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors