]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/parser/BinaryTokenizer.cc
2 * Copyright (C) 1996-2019 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 24 SBuf */
12 #include "ip/Address.h"
13 #include "parser/BinaryTokenizer.h"
15 Parser::BinaryTokenizer::BinaryTokenizer(): BinaryTokenizer(SBuf())
19 Parser::BinaryTokenizer::BinaryTokenizer(const SBuf
&data
, const bool expectMore
):
24 expectMore_(expectMore
)
30 operator <<(std::ostream
&os
, const Parser::BinaryTokenizerContext
*context
)
33 os
<< context
->parent
<< context
->name
;
37 /// debugging helper that prints a "standard" debugs() trailer
38 #define BinaryTokenizer_tail(size, start) \
39 " occupying " << (size) << " bytes @" << (start) << " in " << this << \
40 (expectMore_ ? ';' : '.');
42 /// logs and throws if fewer than size octets remain; no other side effects
44 Parser::BinaryTokenizer::want(uint64_t size
, const char *description
) const
46 if (parsed_
+ size
> data_
.length()) {
47 debugs(24, 5, (parsed_
+ size
- data_
.length()) << " more bytes for " <<
48 context
<< description
<< BinaryTokenizer_tail(size
, parsed_
));
49 Must(expectMore_
); // throw an error on premature input termination
50 throw InsufficientInput();
55 Parser::BinaryTokenizer::got(uint64_t size
, const char *description
) const
57 debugs(24, 7, context
<< description
<<
58 BinaryTokenizer_tail(size
, parsed_
- size
));
61 /// debugging helper for parsed number fields
63 Parser::BinaryTokenizer::got(uint32_t value
, uint64_t size
, const char *description
) const
65 debugs(24, 7, context
<< description
<< '=' << value
<<
66 BinaryTokenizer_tail(size
, parsed_
- size
));
69 /// debugging helper for parsed areas/blobs
71 Parser::BinaryTokenizer::got(const SBuf
&value
, uint64_t size
, const char *description
) const
73 debugs(24, 7, context
<< description
<< '=' <<
74 Raw(nullptr, value
.rawContent(), value
.length()).hex() <<
75 BinaryTokenizer_tail(size
, parsed_
- size
));
79 /// debugging helper for parsed addresses
81 Parser::BinaryTokenizer::got(const Ip::Address
&value
, uint64_t size
, const char *description
) const
83 debugs(24, 7, context
<< description
<< '=' << value
<<
84 BinaryTokenizer_tail(size
, parsed_
- size
));
87 /// debugging helper for skipped fields
89 Parser::BinaryTokenizer::skipped(uint64_t size
, const char *description
) const
91 debugs(24, 7, context
<< description
<< BinaryTokenizer_tail(size
, parsed_
- size
));
95 /// Returns the next ready-for-shift byte, adjusting the number of parsed bytes.
96 /// The larger 32-bit return type helps callers shift/merge octets into numbers.
97 /// This internal method does not perform out-of-bounds checks.
99 Parser::BinaryTokenizer::octet()
101 // While char may be signed, we view data characters as unsigned,
102 // which helps to arrive at the right 32-bit return value.
103 return static_cast<uint8_t>(data_
[parsed_
++]);
107 Parser::BinaryTokenizer::reset(const SBuf
&data
, const bool expectMore
)
109 *this = BinaryTokenizer(data
, expectMore
);
113 Parser::BinaryTokenizer::rollback()
115 parsed_
= syncPoint_
;
119 Parser::BinaryTokenizer::commit()
121 syncPoint_
= parsed_
;
125 Parser::BinaryTokenizer::atEnd() const
127 return parsed_
>= data_
.length();
131 Parser::BinaryTokenizer::uint8(const char *description
)
133 want(1, description
);
134 const uint8_t result
= octet();
135 got(result
, 1, description
);
140 Parser::BinaryTokenizer::uint16(const char *description
)
142 want(2, description
);
143 const uint16_t result
= (octet() << 8) | octet();
144 got(result
, 2, description
);
149 Parser::BinaryTokenizer::uint24(const char *description
)
151 want(3, description
);
152 const uint32_t result
= (octet() << 16) | (octet() << 8) | octet();
153 got(result
, 3, description
);
158 Parser::BinaryTokenizer::uint32(const char *description
)
160 want(4, description
);
161 const uint32_t result
= (octet() << 24) | (octet() << 16) | (octet() << 8) | octet();
162 got(result
, 4, description
);
167 Parser::BinaryTokenizer::area(uint64_t size
, const char *description
)
169 want(size
, description
);
170 const SBuf result
= data_
.substr(parsed_
, size
);
172 got(result
, size
, description
);
176 template <class InAddr
>
178 Parser::BinaryTokenizer::inetAny(const char *description
)
181 const auto size
= sizeof(addr
);
182 want(size
, description
);
183 memcpy(&addr
, data_
.rawContent() + parsed_
, size
);
185 const Ip::Address
result(addr
);
186 got(result
, size
, description
);
191 Parser::BinaryTokenizer::inet4(const char *description
)
193 return inetAny
<struct in_addr
>(description
);
197 Parser::BinaryTokenizer::inet6(const char *description
)
199 return inetAny
<struct in6_addr
>(description
);
203 Parser::BinaryTokenizer::skip(uint64_t size
, const char *description
)
205 want(size
, description
);
207 skipped(size
, description
);
211 * BinaryTokenizer::pstringN() implementations below reduce debugging noise by
212 * not parsing empty areas and not summarizing parsing context.success().
216 Parser::BinaryTokenizer::pstring8(const char *description
)
218 BinaryTokenizerContext
pstring(*this, description
);
219 if (const uint8_t length
= uint8(".length"))
220 return area(length
, ".octets");
225 Parser::BinaryTokenizer::pstring16(const char *description
)
227 BinaryTokenizerContext
pstring(*this, description
);
228 if (const uint16_t length
= uint16(".length"))
229 return area(length
, ".octets");
234 Parser::BinaryTokenizer::pstring24(const char *description
)
236 BinaryTokenizerContext
pstring(*this, description
);
237 if (const uint32_t length
= uint24(".length"))
238 return area(length
, ".octets");