From: Thomas Markwalder Date: Fri, 28 Feb 2025 16:19:36 +0000 (-0500) Subject: [#3750] Backport #3712 to 2.6.2 X-Git-Tag: Kea-2.6.2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=731d00593a7788ddc9cddf921121118b27129a7e;p=thirdparty%2Fkea.git [#3750] Backport #3712 to 2.6.2 Avoid assert on empty packet /src/lib/dhcp/pkt_filter_lpf.cc PktFilterLPF::receive() - throw if packet has no data /src/lib/util/buffer.h InputBuffer::readVecotr() - avoid peek if read request length is 0 /src/lib/util/tests/buffer_unittest.cc Updated test --- diff --git a/src/lib/dhcp/pkt_filter_lpf.cc b/src/lib/dhcp/pkt_filter_lpf.cc index 69bdecc0e1..d800cdce34 100644 --- a/src/lib/dhcp/pkt_filter_lpf.cc +++ b/src/lib/dhcp/pkt_filter_lpf.cc @@ -318,9 +318,14 @@ PktFilterLPF::receive(Iface& iface, const SocketInfo& socket_info) { decodeEthernetHeader(buf, dummy_pkt); decodeIpUdpHeader(buf, dummy_pkt); + auto v4_len = buf.getLength() - buf.getPosition(); + if (v4_len <= 0) { + isc_throw(SocketReadError, "Pkt4FilterLpf packet has no DHCPv4 data"); + } + // Read the DHCP data. std::vector dhcp_buf; - buf.readVector(dhcp_buf, buf.getLength() - buf.getPosition()); + buf.readVector(dhcp_buf, v4_len); // Decode DHCP data into the Pkt4 object. Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(&dhcp_buf[0], dhcp_buf.size())); @@ -344,8 +349,7 @@ PktFilterLPF::receive(Iface& iface, const SocketInfo& socket_info) { struct timeval cmsg_time; memcpy(&cmsg_time, CMSG_DATA(cmsg), sizeof(cmsg_time)); - pkt->addPktEvent(PktEvent::SOCKET_RECEIVED, cmsg_time); - break; + pkt->addPktEvent(PktEvent::SOCKET_RECEIVED, cmsg_time); break; } cmsg = CMSG_NXTHDR(&m, cmsg); diff --git a/src/lib/util/buffer.h b/src/lib/util/buffer.h index 41ecdf3375..c426a14495 100644 --- a/src/lib/util/buffer.h +++ b/src/lib/util/buffer.h @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2024 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2009-2025 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -233,7 +233,8 @@ public: /// @details If specified buffer is too short, it will be expanded using /// vector::resize() method. If the remaining length of the buffer /// is smaller than the specified length, an exception of class - /// @c isc::OutOfRange will be thrown. + /// @c isc::OutOfRange will be thrown. Read length zero results + /// in an empty vector. /// /// @param data Reference to a buffer (data will be stored there). /// @param len Size specified number of bytes to read in a vector. @@ -244,7 +245,9 @@ public: } data.resize(len); - peekData(&data[0], len); + if (len) { + peekData(&data[0], len); + } } /// @brief Read specified number of bytes as a vector. diff --git a/src/lib/util/tests/buffer_unittest.cc b/src/lib/util/tests/buffer_unittest.cc index 66c43e8f21..bae051dd16 100644 --- a/src/lib/util/tests/buffer_unittest.cc +++ b/src/lib/util/tests/buffer_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2024 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2009-2025 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -197,6 +197,12 @@ TEST_F(BufferTest, inputBufferRead) { ASSERT_EQ(sizeof(vdata), datav.size()); ASSERT_EQ(0, memcmp(&vdata[0], testdata, sizeof(testdata))); ASSERT_EQ(sizeof(vdata), ibuffer.getPosition()); + + // Verify that read len of zero results in an empty + // vector without throwing. + datav.resize(8); + ASSERT_NO_THROW(ibuffer.readVector(datav, 0)); + ASSERT_EQ(datav.size(), 0); } TEST_F(BufferTest, outputBufferReadAt) {