Skip to content

Commit 58968ba

Browse files
committed
htp: remove use of deprecated nom 8 functions
1 parent b4290f5 commit 58968ba

10 files changed

Lines changed: 83 additions & 98 deletions

File tree

rust/htp/src/decompressors.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use brotli;
2+
use nom::Parser as _;
23
use std::{
34
io::{Cursor, Write},
45
time::Instant,
@@ -455,11 +456,10 @@ impl GzipBufWriter {
455456
fn parse_start(data: &[u8]) -> nom::IResult<&[u8], u8> {
456457
use nom::bytes::streaming::tag;
457458
use nom::number::streaming::{le_i32, le_u8};
458-
use nom::sequence::tuple;
459459
use nom::Parser as _;
460460

461461
let (rest, (_, flags, _mtime, _xfl, _operating_system)) =
462-
tuple((tag(&b"\x1f\x8b\x08"[..]), le_u8, le_i32, le_u8, le_u8)).parse(data)?;
462+
(tag(&b"\x1f\x8b\x08"[..]), le_u8, le_i32, le_u8, le_u8).parse(data)?;
463463
Ok((rest, flags))
464464
}
465465
}
@@ -468,7 +468,6 @@ impl Write for GzipBufWriter {
468468
fn write(&mut self, data: &[u8]) -> std::io::Result<usize> {
469469
use nom::bytes::streaming::{tag, take_until};
470470
use nom::number::streaming::le_u16;
471-
use nom::sequence::tuple;
472471

473472
const FHCRC: u8 = 1 << 1;
474473
const FEXTRA: u8 = 1 << 2;
@@ -535,10 +534,11 @@ impl Write for GzipBufWriter {
535534
}
536535
GzState::Filename => {
537536
if self.flags & FNAME != 0 {
538-
match tuple((
537+
match (
539538
take_until::<&[u8], &[u8], nom::error::Error<&[u8]>>(b"\0" as &[u8]),
540539
tag(&b"\0"[..]),
541-
))(parse)
540+
)
541+
.parse(parse)
542542
{
543543
Ok((rest, _)) => {
544544
parse = rest;
@@ -558,10 +558,11 @@ impl Write for GzipBufWriter {
558558
}
559559
GzState::Comment => {
560560
if self.flags & FCOMMENT != 0 {
561-
match tuple((
561+
match (
562562
take_until::<&[u8], &[u8], nom::error::Error<&[u8]>>(b"\0" as &[u8]),
563563
tag(&b"\0"[..]),
564-
))(parse)
564+
)
565+
.parse(parse)
565566
{
566567
Ok((rest, _)) => {
567568
parse = rest;

rust/htp/src/headers.rs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use nom::{
55
bytes::streaming::{tag, take_till, take_while, take_while1},
66
character::{is_space, streaming::space0},
77
combinator::{complete, map, not, opt, peek},
8-
sequence::tuple,
98
Err::Incomplete,
109
IResult, Needed, Parser as _,
1110
};
@@ -147,19 +146,19 @@ impl Parser {
147146
if self.side == Side::Response {
148147
alt((
149148
map(
150-
tuple((
149+
(
151150
complete_tag("\n\r\r\n"),
152151
peek(alt((complete_tag("\n"), complete_tag("\r\n")))),
153-
)),
152+
),
154153
|(eol, _)| (eol, HeaderFlags::DEFORMED_EOL),
155154
),
156155
map(
157-
tuple((
156+
(
158157
complete_tag("\r\n\r"),
159158
take_while1(|c| c == b'\r' || c == b' ' || c == b'\t'),
160159
opt(complete_tag("\n")),
161160
not(alt((complete_tag("\n"), complete_tag("\r\n")))),
162-
)),
161+
),
163162
|(eol1, eol2, eol3, _): (&[u8], &[u8], Option<&[u8]>, _)| {
164163
(
165164
&input[..(eol1.len() + eol2.len() + eol3.unwrap_or(b"").len())],
@@ -172,11 +171,11 @@ impl Parser {
172171
} else {
173172
map(
174173
alt((
175-
tuple((
174+
(
176175
complete_tag("\n\r\r\n"),
177176
peek(alt((complete_tag("\n"), complete_tag("\r\n")))),
178-
)),
179-
tuple((complete_tag("\n\r"), peek(complete_tag("\r\n")))),
177+
),
178+
(complete_tag("\n\r"), peek(complete_tag("\r\n"))),
180179
)),
181180
|(eol, _)| (eol, HeaderFlags::DEFORMED_EOL),
182181
)
@@ -198,13 +197,7 @@ impl Parser {
198197

199198
/// Parse one header end of line, and guarantee that it is not folding
200199
fn eol(&self) -> impl Fn(&[u8]) -> IResult<&[u8], ParsedBytes> + '_ {
201-
move |input| {
202-
map(
203-
tuple((self.complete_eol(), not(folding_lws))),
204-
|(end, _)| end,
205-
)
206-
.parse(input)
207-
}
200+
move |input| map((self.complete_eol(), not(folding_lws)), |(end, _)| end).parse(input)
208201
}
209202

210203
/// Parse one null byte or one end of line, and guarantee that it is not folding
@@ -222,16 +215,16 @@ impl Parser {
222215
move |input| {
223216
if self.side == Side::Response {
224217
map(
225-
tuple((
218+
(
226219
map(self.complete_eol_regular(), |eol| (eol, 0)),
227220
folding_lws,
228-
)),
221+
),
229222
|((eol, flags), (lws, other_flags))| (eol, lws, flags | other_flags),
230223
)
231224
.parse(input)
232225
} else {
233226
map(
234-
tuple((self.complete_eol(), folding_lws)),
227+
(self.complete_eol(), folding_lws),
235228
|((eol, flags), (lws, other_flags))| (eol, lws, flags | other_flags),
236229
)
237230
.parse(input)
@@ -307,7 +300,7 @@ impl Parser {
307300
loop {
308301
if self.side == Side::Response {
309302
// Peek ahead for ambiguous name with lws vs. value with folding
310-
match tuple((token_chars, separator_regular)).parse(i) {
303+
match (token_chars, separator_regular).parse(i) {
311304
Ok((_, ((_, tokens, _), (_, _)))) if !tokens.is_empty() => {
312305
flags.unset(HeaderFlags::FOLDING_SPECIAL_CASE);
313306
if value.is_empty() {
@@ -414,8 +407,7 @@ impl Parser {
414407
/// Parse data before an eol with no colon as an empty name with the data as the value
415408
fn header_sans_colon(&self) -> impl Fn(&[u8]) -> IResult<&[u8], Header> + '_ {
416409
move |input| {
417-
let (remaining, (_, value)) =
418-
tuple((not(complete_tag("\r\n")), self.value())).parse(input)?;
410+
let (remaining, (_, value)) = (not(complete_tag("\r\n")), self.value()).parse(input)?;
419411

420412
let flags = value.flags | HeaderFlags::MISSING_COLON;
421413
Ok((
@@ -429,7 +421,7 @@ impl Parser {
429421
fn header_with_colon(&self) -> impl Fn(&[u8]) -> IResult<&[u8], Header> + '_ {
430422
move |input| {
431423
map(
432-
tuple((self.name(), self.separator(), self.value())),
424+
(self.name(), self.separator(), self.value()),
433425
|(mut name, flag, mut value)| {
434426
name.flags |= flag;
435427
value.flags |= flag;
@@ -504,13 +496,13 @@ fn folding_lws(input: &[u8]) -> IResult<&[u8], ParsedBytes<'_>> {
504496

505497
/// Parse a regular separator (colon followed by optional spaces) between header name and value
506498
fn separator_regular(input: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
507-
tuple((complete_tag(":"), space0)).parse(input)
499+
(complete_tag(":"), space0).parse(input)
508500
}
509501

510502
type leading_token_trailing<'a> = (&'a [u8], &'a [u8], &'a [u8]);
511503
/// Parse token characters with leading and trailing whitespace
512504
fn token_chars(input: &[u8]) -> IResult<&[u8], leading_token_trailing<'_>> {
513-
tuple((space0, take_while(is_token), space0)).parse(input)
505+
(space0, take_while(is_token), space0).parse(input)
514506
}
515507

516508
#[cfg(test)]

rust/htp/src/parsers.rs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ use nom::{
2727
fn content_type() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
2828
move |input| {
2929
map(
30-
tuple((
30+
(
3131
take_ascii_whitespace(),
3232
take_till(|c| c == b';' || c == b',' || c == b' '),
33-
)),
33+
),
3434
|(_, content_type)| content_type,
3535
)
3636
.parse(input)
@@ -106,7 +106,7 @@ pub(crate) fn scheme() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
106106
// Scheme test: if it doesn't start with a forward slash character (which it must
107107
// for the contents to be a path or an authority), then it must be the scheme part
108108
map(
109-
tuple((peek(not(tag("/"))), take_until(":"), tag(":"))),
109+
(peek(not(tag("/"))), take_until(":"), tag(":")),
110110
|(_, scheme, _)| scheme,
111111
)
112112
.parse(input)
@@ -125,8 +125,8 @@ pub(crate) fn credentials() -> impl Fn(&[u8]) -> IResult<&[u8], ParsedCredential
125125
// One, three or more slash characters, and it's a path.
126126
// Note: we only attempt to parse authority if we've seen a scheme.
127127
let (input, (_, _, credentials, _)) =
128-
tuple((tag("//"), peek(not(tag("/"))), take_until("@"), tag("@"))).parse(input)?;
129-
let (password, username) = opt(tuple((take_until(":"), tag(":")))).parse(credentials)?;
128+
(tag("//"), peek(not(tag("/"))), take_until("@"), tag("@")).parse(input)?;
129+
let (password, username) = opt((take_until(":"), tag(":"))).parse(credentials)?;
130130
if let Some((username, _)) = username {
131131
Ok((input, (username, Some(password))))
132132
} else {
@@ -141,7 +141,7 @@ pub(crate) fn credentials() -> impl Fn(&[u8]) -> IResult<&[u8], ParsedCredential
141141
/// Returns a tuple of the remaining unconsumed data and the matched ipv6 hostname.
142142
pub(crate) fn ipv6() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
143143
move |input| -> IResult<&[u8], &[u8]> {
144-
let (rest, _) = tuple((tag("["), is_not("/?#]"), opt(tag("]")))).parse(input)?;
144+
let (rest, _) = (tag("["), is_not("/?#]"), opt(tag("]"))).parse(input)?;
145145
Ok((rest, &input[..input.len() - rest.len()]))
146146
}
147147
}
@@ -152,12 +152,12 @@ pub(crate) fn ipv6() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
152152
pub(crate) fn hostname() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
153153
move |input| {
154154
let (input, mut hostname) = map(
155-
tuple((
155+
(
156156
opt(tag("//")), //If it starts with "//", skip (might have parsed a scheme and no creds)
157157
peek(not(tag("/"))), //If it starts with '/', this is a path, not a hostname
158158
many0(tag(" ")),
159159
alt((ipv6(), is_not("/?#:"))),
160-
)),
160+
),
161161
|(_, _, _, hostname)| hostname,
162162
)
163163
.parse(input)?;
@@ -177,7 +177,7 @@ pub(crate) fn port() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
177177
move |input| {
178178
// Must start with ":" for there to be a port to parse
179179
let (input, (_, _, port, _)) =
180-
tuple((tag(":"), many0(tag(" ")), is_not("/?#"), many0(tag(" ")))).parse(input)?;
180+
(tag(":"), many0(tag(" ")), is_not("/?#"), many0(tag(" "))).parse(input)?;
181181
let (_, port) = is_not(" ")(port)?; //we assume there never will be a space in the middle of a port
182182
Ok((input, port))
183183
}
@@ -198,10 +198,7 @@ pub(crate) fn path() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
198198
pub(crate) fn query() -> impl Fn(&[u8]) -> IResult<&[u8], &[u8]> {
199199
move |input| {
200200
// Skip the starting '?'
201-
map(tuple((tag("?"), take_till(|c| c == b'#'))), |(_, query)| {
202-
query
203-
})
204-
.parse(input)
201+
map((tag("?"), take_till(|c| c == b'#')), |(_, query)| query).parse(input)
205202
}
206203
}
207204

@@ -245,15 +242,15 @@ pub(crate) fn parse_hostport(input: &[u8]) -> IResult<&[u8], parsed_hostport<'_>
245242
/// Returns (any unparsed trailing data, (version_number, flag indicating whether input contains trailing and/or leading whitespace and/or leading zeros))
246243
fn protocol_version(input: &[u8]) -> IResult<&[u8], (&[u8], bool)> {
247244
map(
248-
tuple((
245+
(
249246
take_ascii_whitespace(),
250247
tag_no_case("HTTP"),
251248
take_ascii_whitespace(),
252249
tag("/"),
253250
take_while(|c: u8| c.is_ascii_whitespace() || c == b'0'),
254251
alt((tag(".9"), tag("1.0"), tag("1.1"))),
255252
take_ascii_whitespace(),
256-
)),
253+
),
257254
|(_, _, leading, _, trailing, version, _)| {
258255
(version, !leading.is_empty() || !trailing.is_empty())
259256
},
@@ -311,17 +308,17 @@ pub(crate) fn parse_status(status: &[u8]) -> HtpResponseNumber {
311308
/// Parses Digest Authorization request header.
312309
fn parse_authorization_digest(auth_header_value: &[u8]) -> IResult<&[u8], Vec<u8>> {
313310
// Extract the username
314-
let (mut remaining_input, _) = tuple((
311+
let (mut remaining_input, _) = (
315312
take_until("username="),
316313
tag("username="),
317314
take_ascii_whitespace(), // allow lws
318315
tag("\""), // First character after LWS must be a double quote
319-
))(auth_header_value)?;
316+
)
317+
.parse(auth_header_value)?;
320318
let mut result = Vec::new();
321319
// Unescape any escaped double quotes and find the closing quote
322320
loop {
323-
let (remaining, (auth_header, _)) =
324-
tuple((take_until("\""), tag("\""))).parse(remaining_input)?;
321+
let (remaining, (auth_header, _)) = (take_until("\""), tag("\"")).parse(remaining_input)?;
325322
remaining_input = remaining;
326323
result.extend_from_slice(auth_header);
327324
if result.last() == Some(&(b'\\')) {
@@ -339,9 +336,9 @@ fn parse_authorization_digest(auth_header_value: &[u8]) -> IResult<&[u8], Vec<u8
339336
/// Parses Basic Authorization request header.
340337
fn parse_authorization_basic(request_tx: &mut Transaction, auth_header: &Header) -> Result<()> {
341338
// Skip 'Basic<lws>'
342-
let (remaining_input, _) =
343-
tuple((tag_no_case("basic"), take_ascii_whitespace()))(auth_header.value.as_slice())
344-
.map_err(|_| HtpStatus::DECLINED)?;
339+
let (remaining_input, _) = (tag_no_case("basic"), take_ascii_whitespace())
340+
.parse(auth_header.value.as_slice())
341+
.map_err(|_| HtpStatus::DECLINED)?;
345342
// Decode base64-encoded data
346343
let decoded = STANDARD
347344
.decode(remaining_input)
@@ -383,11 +380,12 @@ pub(crate) fn parse_authorization(request_tx: &mut Transaction) -> Result<()> {
383380
}
384381
} else if auth_header.value.starts_with_nocase("bearer") {
385382
request_tx.request_auth_type = HtpAuthType::BEARER;
386-
let (token, _) = tuple((
383+
let (token, _) = (
387384
tag_no_case("bearer"),
388385
take_ascii_whitespace(), // allow lws
389-
))(auth_header.value.as_slice())
390-
.map_err(|_| HtpStatus::DECLINED)?;
386+
)
387+
.parse(auth_header.value.as_slice())
388+
.map_err(|_| HtpStatus::DECLINED)?;
391389
request_tx.request_auth_token = Some(Bstr::from(token));
392390
} else {
393391
// Unrecognized authentication method

rust/htp/src/request.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
},
1919
HtpStatus,
2020
};
21-
use nom::sequence::tuple;
21+
use nom::Parser as _;
2222
use std::{
2323
cmp::{min, Ordering},
2424
mem::take,
@@ -272,7 +272,7 @@ impl ConnectionParser {
272272
// The request method starts at the beginning of the
273273
// line and ends with the first whitespace character.
274274
// We skip leading whitespace as IIS allows this.
275-
let res = tuple((take_is_space, take_not_is_space))(buffered.as_slice());
275+
let res = (take_is_space, take_not_is_space).parse(buffered.as_slice());
276276
if let Ok((_, (_, method))) = res {
277277
if HtpMethod::new(method) == HtpMethod::Unknown {
278278
self.request_status = HtpStreamState::TUNNEL;
@@ -889,18 +889,18 @@ impl ConnectionParser {
889889
}
890890
// The request method starts at the beginning of the
891891
// line and ends with the first whitespace character.
892-
let mut method_parser = tuple
892+
let mut method_parser =
893893
// skip past leading whitespace. IIS allows this
894-
((take_is_space,
894+
(take_is_space,
895895
take_not_is_space,
896896
// Ignore whitespace after request method. The RFC allows
897897
// for only one SP, but then suggests any number of SP and HT
898898
// should be permitted. Apache uses isspace(), which is even
899899
// more permitting, so that's what we use here.
900900
take_is_space
901-
));
901+
);
902902

903-
if let Ok((remaining, (ls, method, ws))) = method_parser(data) {
903+
if let Ok((remaining, (ls, method, ws))) = method_parser.parse(data) {
904904
if !ls.is_empty() {
905905
htp_warn!(
906906
self.logger,
@@ -1369,7 +1369,7 @@ impl ConnectionParser {
13691369
//closing
13701370
return self.state_request_complete(input);
13711371
}
1372-
let res = tuple((take_is_space, take_not_is_space))(&data);
1372+
let res = (take_is_space, take_not_is_space).parse(&data);
13731373

13741374
if let Ok((_, (_, method))) = res {
13751375
if method.is_empty() {

rust/htp/src/request_generic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
FlagOperations, HtpFlags,
1313
},
1414
};
15-
use nom::{bytes::complete::take_while, error::ErrorKind, sequence::tuple};
15+
use nom::{bytes::complete::take_while, error::ErrorKind};
1616
use std::cmp::Ordering;
1717

1818
impl ConnectionParser {

0 commit comments

Comments
 (0)