SrvRqst: Add bounds checking on buffer parsing
There are multiple length fields provided by the user in this command.
Need to ensure those lengths do not exceed the input buffer size.
Tested:
- Executed new unit tests successfully
Change-Id: Ife4b74d7541d6939bdc30a381fc5cc80cfd24057
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/slp_parser.cpp b/slp_parser.cpp
index f99b527..8901726 100644
--- a/slp_parser.cpp
+++ b/slp_parser.cpp
@@ -233,13 +233,27 @@
/* 1) Parse the PRList. */
uint16_t prListLen;
- std::copy_n(buff.data() + slp::request::OFFSET_PR_LEN,
- slp::request::SIZE_PRLIST, (uint8_t*)&prListLen);
+ uint32_t pos = slp::header::MIN_LEN + req.header.langtagLen;
+ if ((pos + slp::request::SIZE_PRLIST) > buff.size())
+ {
+ std::cerr << "PRList length field is greater then input buffer: "
+ << (pos + slp::request::SIZE_PRLIST) << " / " << buff.size()
+ << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
+ std::copy_n(buff.data() + pos, slp::request::SIZE_PRLIST,
+ (uint8_t*)&prListLen);
- auto pos = slp::request::OFFSET_PR_LEN + slp::request::SIZE_PRLIST;
+ pos += slp::request::SIZE_PRLIST;
prListLen = endian::from_network(prListLen);
-
+ if ((pos + prListLen) > buff.size())
+ {
+ std::cerr << "Length of PRList is greater then input buffer: "
+ << (slp::request::OFFSET_PR + prListLen) << " / "
+ << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
req.body.srvrqst.prList.insert(0, (const char*)buff.data() + pos,
prListLen);
@@ -247,6 +261,13 @@
/* 2) Parse the <service-type> string. */
uint16_t srvTypeLen;
+ if ((pos + slp::request::SIZE_SERVICE_TYPE) > buff.size())
+ {
+ std::cerr << "SrvType length field is greater then input buffer: "
+ << (pos + slp::request::SIZE_SERVICE_TYPE) << " / "
+ << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
std::copy_n(buff.data() + pos, slp::request::SIZE_SERVICE_TYPE,
(uint8_t*)&srvTypeLen);
@@ -254,6 +275,12 @@
pos += slp::request::SIZE_SERVICE_TYPE;
+ if ((pos + srvTypeLen) > buff.size())
+ {
+ std::cerr << "Length of SrvType is greater then input buffer: "
+ << (pos + srvTypeLen) << " / " << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
req.body.srvrqst.srvType.insert(0, (const char*)buff.data() + pos,
srvTypeLen);
@@ -261,6 +288,13 @@
/* 3) Parse the <scope-list> string. */
uint16_t scopeListLen;
+ if ((pos + slp::request::SIZE_SCOPE) > buff.size())
+ {
+ std::cerr << "Scope List length field is greater then input buffer: "
+ << (pos + slp::request::SIZE_SCOPE) << " / " << buff.size()
+ << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
std::copy_n(buff.data() + pos, slp::request::SIZE_SCOPE,
(uint8_t*)&scopeListLen);
@@ -268,6 +302,12 @@
pos += slp::request::SIZE_SCOPE;
+ if ((pos + scopeListLen) > buff.size())
+ {
+ std::cerr << "Length of Scope List is greater then input buffer: "
+ << (pos + scopeListLen) << " / " << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
req.body.srvrqst.scopeList.insert(0, (const char*)buff.data() + pos,
scopeListLen);
@@ -275,12 +315,25 @@
/* 4) Parse the <predicate> string. */
uint16_t predicateLen;
+ if ((pos + slp::request::SIZE_PREDICATE) > buff.size())
+ {
+ std::cerr << "Predicate length field is greater then input buffer: "
+ << (pos + slp::request::SIZE_PREDICATE) << " / "
+ << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
std::copy_n(buff.data() + pos, slp::request::SIZE_PREDICATE,
(uint8_t*)&predicateLen);
predicateLen = endian::from_network(predicateLen);
pos += slp::request::SIZE_PREDICATE;
+ if ((pos + predicateLen) > buff.size())
+ {
+ std::cerr << "Length of Predicate is greater then input buffer: "
+ << (pos + predicateLen) << " / " << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
req.body.srvrqst.predicate.insert(0, (const char*)buff.data() + pos,
predicateLen);
@@ -288,12 +341,25 @@
/* 5) Parse the <SLP SPI> string. */
uint16_t spistrLen;
+ if ((pos + slp::request::SIZE_SLPI) > buff.size())
+ {
+ std::cerr << "SLP SPI length field is greater then input buffer: "
+ << (pos + slp::request::SIZE_SLPI) << " / " << buff.size()
+ << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
std::copy_n(buff.data() + pos, slp::request::SIZE_SLPI,
(uint8_t*)&spistrLen);
spistrLen = endian::from_network(spistrLen);
pos += slp::request::SIZE_SLPI;
+ if ((pos + spistrLen) > buff.size())
+ {
+ std::cerr << "Length of SLP SPI is greater then input buffer: "
+ << (pos + spistrLen) << " / " << buff.size() << std::endl;
+ return (int)slp::Error::PARSE_ERROR;
+ }
req.body.srvrqst.spistr.insert(0, (const char*)buff.data() + pos,
spistrLen);