]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/parser/BinaryTokenizer.cc
be16bdc548db82cfbaf82ecb8e7598f246490d2c
2 * Copyright (C) 1996-2025 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 */
13 #include "ip/Address.h"
14 #include "parser/BinaryTokenizer.h"
16 Parser::BinaryTokenizer::BinaryTokenizer(): BinaryTokenizer(SBuf())
20 Parser::BinaryTokenizer::BinaryTokenizer(const SBuf
&data
, const bool expectMore
):
25 expectMore_(expectMore
)
31 operator <<(std::ostream
&os
, const Parser::BinaryTokenizerContext
*context
)
34 os
<< context
->parent
<< context
->name
;
38 /// debugging helper that prints a "standard" debugs() trailer
39 #define BinaryTokenizer_tail(size, start) \
40 " occupying " << (size) << " bytes @" << (start) << " in " << this << \
41 (expectMore_ ? ';' : '.');
43 /// logs and throws if fewer than size octets remain; no other side effects
45 Parser::BinaryTokenizer::want(uint64_t size
, const char *description
) const
47 if (parsed_
+ size
> data_
.length()) {
48 debugs(24, 5, (parsed_
+ size
- data_
.length()) << " more bytes for " <<
49 context
<< description
<< BinaryTokenizer_tail(size
, parsed_
));
50 Must(expectMore_
); // throw an error on premature input termination
51 throw InsufficientInput();
56 Parser::BinaryTokenizer::got(uint64_t size
, const char *description
) const
58 debugs(24, 7, context
<< description
<<
59 BinaryTokenizer_tail(size
, parsed_
- size
));
62 /// debugging helper for parsed number fields
64 Parser::BinaryTokenizer::got(uint32_t value
, uint64_t size
, const char *description
) const
66 debugs(24, 7, context
<< description
<< '=' << value
<<
67 BinaryTokenizer_tail(size
, parsed_
- size
));
70 /// debugging helper for parsed areas/blobs
72 Parser::BinaryTokenizer::got(const SBuf
&value
, uint64_t size
, const char *description
) const
74 debugs(24, 7, context
<< description
<< '=' <<
75 Raw(nullptr, value
.rawContent(), value
.length()).hex() <<
76 BinaryTokenizer_tail(size
, parsed_
- size
));
80 /// debugging helper for parsed addresses
82 Parser::BinaryTokenizer::got(const Ip::Address
&value
, uint64_t size
, const char *description
) const
84 debugs(24, 7, context
<< description
<< '=' << value
<<
85 BinaryTokenizer_tail(size
, parsed_
- size
));
88 /// debugging helper for skipped fields
90 Parser::BinaryTokenizer::skipped(uint64_t size
, const char *description
) const
92 debugs(24, 7, context
<< description
<< BinaryTokenizer_tail(size
, parsed_
- size
));
96 /// Returns the next ready-for-shift byte, adjusting the number of parsed bytes.
97 /// The larger 32-bit return type helps callers shift/merge octets into numbers.
98 /// This internal method does not perform out-of-bounds checks.
100 Parser::BinaryTokenizer::octet()
102 // While char may be signed, we view data characters as unsigned,
103 // which helps to arrive at the right 32-bit return value.
104 return static_cast<uint8_t>(data_
[parsed_
++]);
108 Parser::BinaryTokenizer::reset(const SBuf
&data
, const bool expectMore
)
110 *this = BinaryTokenizer(data
, expectMore
);
114 Parser::BinaryTokenizer::rollback()
116 parsed_
= syncPoint_
;
120 Parser::BinaryTokenizer::commit()
122 syncPoint_
= parsed_
;
126 Parser::BinaryTokenizer::atEnd() const
128 return parsed_
>= data_
.length();
132 Parser::BinaryTokenizer::uint8(const char *description
)
134 want(1, description
);
135 const uint8_t result
= octet();
136 got(result
, 1, description
);
141 Parser::BinaryTokenizer::uint16(const char *description
)
143 want(2, description
);
144 const uint16_t result
= (octet() << 8) | octet();
145 got(result
, 2, description
);
150 Parser::BinaryTokenizer::uint24(const char *description
)
152 want(3, description
);
153 const uint32_t result
= (octet() << 16) | (octet() << 8) | octet();
154 got(result
, 3, description
);
159 Parser::BinaryTokenizer::uint32(const char *description
)
161 want(4, description
);
162 const uint32_t result
= (octet() << 24) | (octet() << 16) | (octet() << 8) | octet();
163 got(result
, 4, description
);
168 Parser::BinaryTokenizer::area(uint64_t size
, const char *description
)
170 want(size
, description
);
171 const SBuf result
= data_
.substr(parsed_
, size
);
173 got(result
, size
, description
);
177 template <class InAddr
>
179 Parser::BinaryTokenizer::inetAny(const char *description
)
182 const auto size
= sizeof(addr
);
183 want(size
, description
);
184 memcpy(&addr
, data_
.rawContent() + parsed_
, size
);
186 const Ip::Address
result(addr
);
187 got(result
, size
, description
);
192 Parser::BinaryTokenizer::inet4(const char *description
)
194 return inetAny
<struct in_addr
>(description
);
198 Parser::BinaryTokenizer::inet6(const char *description
)
200 return inetAny
<struct in6_addr
>(description
);
204 Parser::BinaryTokenizer::skip(uint64_t size
, const char *description
)
206 want(size
, description
);
208 skipped(size
, description
);
212 * BinaryTokenizer::pstringN() implementations below reduce debugging noise by
213 * not parsing empty areas and not summarizing parsing context.success().
217 Parser::BinaryTokenizer::pstring8(const char *description
)
219 BinaryTokenizerContext
pstring(*this, description
);
220 if (const uint8_t length
= uint8(".length"))
221 return area(length
, ".octets");
226 Parser::BinaryTokenizer::pstring16(const char *description
)
228 BinaryTokenizerContext
pstring(*this, description
);
229 if (const uint16_t length
= uint16(".length"))
230 return area(length
, ".octets");
235 Parser::BinaryTokenizer::pstring24(const char *description
)
237 BinaryTokenizerContext
pstring(*this, description
);
238 if (const uint32_t length
= uint24(".length"))
239 return area(length
, ".octets");