Skip to content

Commit

Permalink
Eliminated code duplication in ProxyProtocol::IntegerToFieldType()
Browse files Browse the repository at this point in the history
by reusing a new ParseInteger() template.
  • Loading branch information
eduard-bagdasaryan committed Nov 9, 2023
1 parent af8b89b commit 2f72f5f
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 78 deletions.
55 changes: 0 additions & 55 deletions src/format/Token.cc
Original file line number Diff line number Diff line change
Expand Up @@ -287,61 +287,6 @@ Format::Token::scanForToken(TokenTableEntry const table[], const char *cur)
return cur;
}

/// parses a decimal integer that fits the specified Integer type
template <typename Integer>
static Integer
ParseInteger(const char *description, const SBuf &rawInput)
{
Parser::Tokenizer tok(rawInput);
if (tok.skip('0')) {
if (!tok.atEnd()) {
// e.g., 077, 0xFF, 0b101, or 0.1
throw TextException(ToSBuf("Malformed ", description,
": Expected a decimal integer without leading zeros but got '",
rawInput, "'"), Here());
}
return Integer(0);
}
// else the value might still be zero (e.g., -0)

const auto lowerLimit = std::numeric_limits<Integer>::min();
const auto upperLimit = std::numeric_limits<Integer>::max();

// check that our caller is compatible with Tokenizer::int64() use below
using ParsedInteger = int64_t;
static_assert(lowerLimit >= std::numeric_limits<ParsedInteger>::min());
static_assert(upperLimit <= std::numeric_limits<ParsedInteger>::max());

ParsedInteger rawInteger = 0;
if (!tok.int64(rawInteger, 10, true)) {
// e.g., FF
throw TextException(ToSBuf("Malformed ", description,
": Expected a decimal integer but got '",
rawInput, "'"), Here());
}

if (!tok.atEnd()) {
// e.g., 1,000, 1.0, or 1e6
throw TextException(ToSBuf("Malformed ", description,
": Trailing garbage after ", rawInteger, " in '",
rawInput, "'"), Here());
}

if (rawInteger > upperLimit) {
throw TextException(ToSBuf("Malformed ", description,
": Expected an integer value not exceeding ", upperLimit,
" but got ", rawInteger), Here());
}

if (rawInteger < lowerLimit) {
throw TextException(ToSBuf("Malformed ", description,
": Expected an integer value not below ", lowerLimit,
" but got ", rawInteger), Here());
}

return Integer(rawInteger);
}

/* parses a single token. Returns the token length in characters,
* and fills in the lt item with the token information.
* def is for sure null-terminated
Expand Down
57 changes: 57 additions & 0 deletions src/parser/Tokenizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,62 @@ class Tokenizer

} /* namespace Parser */

#include "sbuf/Stream.h"

/// parses a decimal integer that fits the specified Integer type
template <typename Integer>
static Integer
ParseInteger(const char *description, const SBuf &rawInput)
{
Parser::Tokenizer tok(rawInput);
if (tok.skip('0')) {
if (!tok.atEnd()) {
// e.g., 077, 0xFF, 0b101, or 0.1
throw TextException(ToSBuf("Malformed ", description,
": Expected a decimal integer without leading zeros but got '",
rawInput, "'"), Here());
}
return Integer(0);
}
// else the value might still be zero (e.g., -0)

const auto lowerLimit = std::numeric_limits<Integer>::min();
const auto upperLimit = std::numeric_limits<Integer>::max();

// check that our caller is compatible with Tokenizer::int64() use below
using ParsedInteger = int64_t;
static_assert(lowerLimit >= std::numeric_limits<ParsedInteger>::min());
static_assert(upperLimit <= std::numeric_limits<ParsedInteger>::max());

ParsedInteger rawInteger = 0;
if (!tok.int64(rawInteger, 10, true)) {
// e.g., FF
throw TextException(ToSBuf("Malformed ", description,
": Expected a decimal integer but got '",
rawInput, "'"), Here());
}

if (!tok.atEnd()) {
// e.g., 1,000, 1.0, or 1e6
throw TextException(ToSBuf("Malformed ", description,
": Trailing garbage after ", rawInteger, " in '",
rawInput, "'"), Here());
}

if (rawInteger > upperLimit) {
throw TextException(ToSBuf("Malformed ", description,
": Expected an integer value not exceeding ", upperLimit,
" but got ", rawInteger), Here());
}

if (rawInteger < lowerLimit) {
throw TextException(ToSBuf("Malformed ", description,
": Expected an integer value not below ", lowerLimit,
" but got ", rawInteger), Here());
}

return Integer(rawInteger);
}

#endif /* SQUID_PARSER_TOKENIZER_H_ */

24 changes: 1 addition & 23 deletions src/proxyp/Elements.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,7 @@ ProxyProtocol::NameToFieldType(const SBuf &name)
ProxyProtocol::Two::FieldType
ProxyProtocol::IntegerToFieldType(const SBuf &rawInteger)
{
int64_t tlvType = 0;

Parser::Tokenizer ptok(rawInteger);
if (ptok.skip('0')) {
if (!ptok.atEnd())
throw TexcHere(ToSBuf("Invalid PROXY protocol TLV type value. ",
"Expected a decimal integer without leading zeros but got '",
rawInteger, "'")); // e.g., 077, 0xFF, or 0b101
// tlvType stays zero
} else {
Must(ptok.int64(tlvType, 10, false)); // the first character is a DIGIT
if (!ptok.atEnd())
throw TexcHere(ToSBuf("Invalid PROXY protocol TLV type value. ",
"Trailing garbage after ", tlvType, " in '",
rawInteger, "'")); // e.g., 1.0 or 5e0
}

const auto limit = std::numeric_limits<uint8_t>::max();
if (tlvType > limit)
throw TexcHere(ToSBuf("Invalid PROXY protocol TLV type value. ",
"Expected an integer less than ", limit,
" but got '", tlvType, "'"));

const auto tlvType = ParseInteger<int64_t>("proxy protocol TLV type value", rawInteger);
return Two::FieldType(tlvType);
}

Expand Down

0 comments on commit 2f72f5f

Please sign in to comment.