ContentLengthInterpreter.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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(aDebugLevel),
25  sawBad(false),
26  needsSanitizing(false),
27  sawGood(false)
28 {
29 }
30 
32 bool
33 Http::ContentLengthInterpreter::goodSuffix(const char *suffix, const char * const end) const
34 {
35  // optimize for the common case that does not need delimiters
36  if (suffix == end)
37  return true;
38 
39  for (const CharacterSet &delimiters = Http::One::Parser::DelimiterCharacters();
40  suffix < end; ++suffix) {
41  if (!delimiters[*suffix])
42  return false;
43  }
44  // needsSanitizing = true; // TODO: Always remove trailing whitespace?
45  return true; // including empty suffix
46 }
47 
50 bool
51 Http::ContentLengthInterpreter::checkValue(const char *rawValue, const int valueSize)
52 {
53  Must(!sawBad);
54 
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));
60  sawBad = true;
61  return false;
62  }
63 
64  if (latestValue < 0) {
65  debugs(55, debugLevel, "WARNING: Negative" << Raw("Content-Length", rawValue, valueSize));
66  sawBad = true;
67  return false;
68  }
69 
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));
73  sawBad = true;
74  return false;
75  }
76 
77  if (sawGood) {
78  /* we have found at least two, possibly identical values */
79 
80  needsSanitizing = true; // replace identical values with a single value
81 
82  const bool conflicting = value != latestValue;
83  if (conflicting)
84  headerWideProblem = "Conflicting"; // overwrite any lesser problem
85  else if (!headerWideProblem) // preserve a possibly worse problem
86  headerWideProblem = "Duplicate";
87 
88  // with relaxed_header_parser, identical values are permitted
89  sawBad = !Config.onoff.relaxed_header_parser || conflicting;
90  return false; // conflicting or duplicate
91  }
92 
93  sawGood = true;
94  value = latestValue;
95  return true;
96 }
97 
99 bool
101 {
102  Must(!sawBad);
103 
105  debugs(55, debugLevel, "WARNING: List-like" << Raw("Content-Length", list.rawBuf(), list.size()));
106  sawBad = true;
107  return false;
108  }
109 
110  needsSanitizing = true; // remove extra commas (at least)
111 
112  const char *pos = nullptr;
113  const char *item = nullptr;;
114  int ilen = -1;
115  while (strListGetItem(&list, ',', &item, &ilen, &pos)) {
116  if (!checkValue(item, ilen) && sawBad)
117  break;
118  // keep going after a duplicate value to find conflicting ones
119  }
120  return false; // no need to keep this list field; it will be sanitized away
121 }
122 
123 bool
125 {
126  if (sawBad)
127  return false; // one rotten apple is enough to spoil all of them
128 
129  // TODO: Optimize by always parsing the first integer first.
130  return rawValue.pos(',') ?
131  checkList(rawValue) :
132  checkValue(rawValue.rawBuf(), rawValue.size());
133 }
134 
ContentLengthInterpreter(const int aDebugLevel)
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
const char * pos(char const *aString) const
Definition: String.cc:498
size_type size() const
Definition: SquidString.h:71
bool checkList(const String &list)
handles Content-Length: a, b, c
int relaxed_header_parser
Definition: SquidConfig.h:315
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define DBG_IMPORTANT
Definition: Debug.h:45
char const * rawBuf() const
Definition: SquidString.h:84
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:17
struct SquidConfig::@112 onoff
#define Must(cond)
Definition: TextException.h:89
bool checkValue(const char *start, const int size)
Definition: Debug.h:179
class SquidConfig Config
Definition: SquidConfig.cc:12
#define false
Definition: GnuRegex.c:233

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors