Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/bm_sim/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ void extract_VL(Header *hdr,
// get_nbytes_packet counts the VL field in the header as 0 bits
auto bytes_to_extract = static_cast<size_t>(
hdr->get_nbytes_packet() + nbits / 8);
if (pkt->get_ingress_length() - *bytes_parsed < bytes_to_extract)
if (*bytes_parsed > pkt->get_data_size() ||
pkt->get_data_size() - *bytes_parsed < bytes_to_extract)
throw parser_exception_core(ErrorCodeMap::Core::PacketTooShort);

if (max_header_bytes != 0 && max_header_bytes < bytes_to_extract)
Expand Down Expand Up @@ -443,7 +444,8 @@ struct ParserOpShift : ParserOp {
void operator()(Packet *pkt, const char *data,
size_t *bytes_parsed) const override {
(void) data;
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes)
if (*bytes_parsed > pkt->get_data_size() ||
pkt->get_data_size() - *bytes_parsed < shift_bytes)
throw parser_exception_core(ErrorCodeMap::Core::PacketTooShort);
*bytes_parsed += shift_bytes;
}
Expand Down Expand Up @@ -475,7 +477,8 @@ ParserOpAdvance<Data>::operator()(Packet *pkt, const char *data,
}
const auto shift_bytes_uint = shift_bits_uint / 8;
BMLOG_DEBUG_PKT(*pkt, "Advancing by {} bytes", shift_bytes_uint);
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes_uint)
if (*bytes_parsed > pkt->get_data_size() ||
pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
throw parser_exception_core(ErrorCodeMap::Core::PacketTooShort);
*bytes_parsed += shift_bytes_uint;
}
Expand All @@ -499,7 +502,8 @@ ParserOpAdvance<ArithExpression>::operator()(Packet *pkt, const char *data,
}
const auto shift_bytes_uint = shift_bits_uint / 8;
BMLOG_DEBUG_PKT(*pkt, "Advancing by {} bytes", shift_bytes_uint);
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes_uint)
if (*bytes_parsed > pkt->get_data_size() ||
pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
throw parser_exception_core(ErrorCodeMap::Core::PacketTooShort);
*bytes_parsed += shift_bytes_uint;
}
Expand All @@ -522,7 +526,8 @@ ParserOpAdvance<field_t>::operator()(Packet *pkt, const char *data,
}
const auto shift_bytes_uint = shift_bits_uint / 8;
BMLOG_DEBUG_PKT(*pkt, "Advancing by {} bytes", shift_bytes_uint);
if (pkt->get_ingress_length() - *bytes_parsed < shift_bytes_uint)
if (*bytes_parsed > pkt->get_data_size() ||
pkt->get_data_size() - *bytes_parsed < shift_bytes_uint)
throw parser_exception_core(ErrorCodeMap::Core::PacketTooShort);
*bytes_parsed += shift_bytes_uint;
}
Expand Down
40 changes: 40 additions & 0 deletions tests/test_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,34 @@ TEST_F(ParserShiftTest, AdvanceByFieldInvalidArgument) {
parse_and_check_error(&packet, ErrorCodeMap::Core::ParserInvalidArgument);
}

TEST_F(ParserShiftTest, ShiftAllowsExtendedPacketData) {
parse_state.add_shift(2); // shift past original packet length
parse_state.add_extract(testHeader);

std::string packet_data("\xaa\xbb\xcc");
auto packet = get_pkt(packet_data);
packet.set_ingress_length(1); // simulate recirculated packet with new bytes

parse_and_check_no_error(&packet);
const auto &f = packet.get_phv()->get_field(testHeader, 0); // f8
ASSERT_EQ(static_cast<unsigned char>(packet_data.at(2)),
f.get<unsigned char>());
}

TEST_F(ParserShiftTest, AdvanceAllowsExtendedPacketData) {
parse_state.add_advance_from_data(Data(2 * 8)); // shift past original length
parse_state.add_extract(testHeader);

std::string packet_data("\xaa\xbb\xcc");
auto packet = get_pkt(packet_data);
packet.set_ingress_length(1); // simulate recirculated packet with new bytes

parse_and_check_no_error(&packet);
const auto &f = packet.get_phv()->get_field(testHeader, 0); // f8
ASSERT_EQ(static_cast<unsigned char>(packet_data.at(2)),
f.get<unsigned char>());
}


class ParserExtractVLTest : public ParserTestGeneric {
protected:
Expand Down Expand Up @@ -1992,6 +2020,18 @@ TEST_F(ParserExtractVLTest, InvalidArgument) {
parse_and_check_error(&packet, ErrorCodeMap::Core::ParserInvalidArgument);
}

TEST_F(ParserExtractVLTest, ResubmittedPacketLargerThanIngressLength) {
parse_state.add_extract_VL(testHeader, make_expr(max_header_bytes * 8),
max_header_bytes);
std::string packet_data(max_header_bytes, '\xaa');
auto packet = get_pkt(packet_data);
packet.set_ingress_length(max_header_bytes / 2);

parse_and_check_no_error(&packet);
const auto &f = packet.get_phv()->get_field(testHeader, 0); // fVL
ASSERT_EQ(packet_data, f.get_string());
}


// Google Test fixture for header union stacks
class HeaderUnionStackParserTest : public ParserTestGeneric {
Expand Down
Loading