From: Marcin Siodelski Date: Fri, 16 Nov 2018 18:30:27 +0000 (+0100) Subject: [#53,!125] Ensure that the HW address and client id buffers are non-zero. X-Git-Tag: 177-serialize-netconf-tests_base~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56bbd60d0168d74b8025c5d845f0e5109c26d7a3;p=thirdparty%2Fkea.git [#53,!125] Ensure that the HW address and client id buffers are non-zero. --- diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index 696a829cb8..6e241fe174 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -464,14 +464,18 @@ public: if (hwaddr) { hwaddr_ = hwaddr->hwaddr_; hwaddr_length_ = hwaddr->hwaddr_.size(); - bind_[1].buffer_type = MYSQL_TYPE_BLOB; - // Do not reference the buffer if it is empty and just leave it - // set to 0 (memset set it to 0 above). - if (!hwaddr_.empty()) { - bind_[1].buffer = reinterpret_cast(&(hwaddr_[0])); + // Make sure that the buffer has at least length of 1, even if + // empty HW address is passed. This is required by some of the + // MySQL connectors that the buffer is set to non-null value. + // Otherwise, null value would be inserted into the database, + // rather than empty string. + if (hwaddr_.empty()) { + hwaddr_.resize(1); } + bind_[1].buffer_type = MYSQL_TYPE_BLOB; + bind_[1].buffer = reinterpret_cast(&(hwaddr_[0])); bind_[1].buffer_length = hwaddr_length_; bind_[1].length = &hwaddr_length_; } else { @@ -490,14 +494,18 @@ public: if (lease_->client_id_) { client_id_ = lease_->client_id_->getClientId(); client_id_length_ = client_id_.size(); - bind_[2].buffer_type = MYSQL_TYPE_BLOB; - // Do not reference the buffer if it is empty and just leave it - // set to 0 (memset set it to 0 above). - if (!client_id_.empty()) { - bind_[2].buffer = reinterpret_cast(&client_id_[0]); + // Make sure that the buffer has at least length of 1, even if + // empty HW address is passed. This is required by some of the + // MySQL connectors that the buffer is set to non-null value. + // Otherwise, null value would be inserted into the database, + // rather than empty string. + if (client_id_.empty()) { + client_id_.resize(1); } + bind_[2].buffer_type = MYSQL_TYPE_BLOB; + bind_[2].buffer = reinterpret_cast(&client_id_[0]); bind_[2].buffer_length = client_id_length_; bind_[2].length = &client_id_length_; // bind_[2].is_null = &MLM_FALSE; // commented out for performance @@ -1035,6 +1043,16 @@ public: if (hwaddr) { hwaddr_ = hwaddr->hwaddr_; hwaddr_length_ = hwaddr->hwaddr_.size(); + + // Make sure that the buffer has at least length of 1, even if + // empty HW address is passed. This is required by some of the + // MySQL connectors that the buffer is set to non-null value. + // Otherwise, null value would be inserted into the database, + // rather than empty string. + if (hwaddr_.empty()) { + hwaddr_.resize(1); + } + bind_[12].buffer_type = MYSQL_TYPE_BLOB; bind_[12].buffer = reinterpret_cast(&(hwaddr_[0])); bind_[12].buffer_length = hwaddr_length_; @@ -1912,20 +1930,20 @@ MySqlLeaseMgr::getLease4(const HWAddr& hwaddr) const { inbind[0].buffer_type = MYSQL_TYPE_BLOB; unsigned long hwaddr_length = hwaddr.hwaddr_.size(); - uint8_t* data = 0; - - // Only reference the buffer if the buffer has any data. Otherwise - // leave it set to 0 (memset set it to 0 above). - if (hwaddr_length > 0) { - // As "buffer" is "char*" - even though the data is being read - we need - // to cast away the "const"ness as well as reinterpreting the data as - // a "char*". (We could avoid the "const_cast" by copying the data to a - // local variable, but as the data is only being read, this introduces - // an unnecessary copy). - data = const_cast(&hwaddr.hwaddr_[0]); - inbind[0].buffer = reinterpret_cast(data); - } + // If the data happens to be empty, we have to create a 1 byte dummy + // buffer and pass it to the binding. + std::vector single_byte_vec(1); + + // As "buffer" is "char*" - even though the data is being read - we need + // to cast away the "const"ness as well as reinterpreting the data as + // a "char*". (We could avoid the "const_cast" by copying the data to a + // local variable, but as the data is only being read, this introduces + // an unnecessary copy). + uint8_t* data = !hwaddr.hwaddr_.empty() ? const_cast(&hwaddr.hwaddr_[0]) + : &single_byte_vec[0]; + + inbind[0].buffer = reinterpret_cast(data); inbind[0].buffer_length = hwaddr_length; inbind[0].length = &hwaddr_length; @@ -1949,20 +1967,20 @@ MySqlLeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const { inbind[0].buffer_type = MYSQL_TYPE_BLOB; unsigned long hwaddr_length = hwaddr.hwaddr_.size(); - uint8_t* data = 0; - - // Only reference the buffer if the buffer has any data. Otherwise - // leave it set to 0 (memset set it to 0 above). - if (hwaddr_length > 0) { - // As "buffer" is "char*" - even though the data is being read - we need - // to cast away the "const"ness as well as reinterpreting the data as - // a "char*". (We could avoid the "const_cast" by copying the data to a - // local variable, but as the data is only being read, this introduces - // an unnecessary copy). - data = const_cast(&hwaddr.hwaddr_[0]); - inbind[0].buffer = reinterpret_cast(data); - } + // If the data happens to be empty, we have to create a 1 byte dummy + // buffer and pass it to the binding. + std::vector single_byte_vec(1); + + // As "buffer" is "char*" - even though the data is being read - we need + // to cast away the "const"ness as well as reinterpreting the data as + // a "char*". (We could avoid the "const_cast" by copying the data to a + // local variable, but as the data is only being read, this introduces + // an unnecessary copy). + uint8_t* data = !hwaddr.hwaddr_.empty() ? const_cast(&hwaddr.hwaddr_[0]) + : &single_byte_vec[0]; + + inbind[0].buffer = reinterpret_cast(data); inbind[0].buffer_length = hwaddr_length; inbind[0].length = &hwaddr_length; @@ -1991,12 +2009,13 @@ MySqlLeaseMgr::getLease4(const ClientId& clientid) const { std::vector client_data = clientid.getClientId(); unsigned long client_data_length = client_data.size(); - // Only reference the buffer if the buffer has any data. Otherwise - // leave it set to 0 (memset set it to 0 above). - if (client_data_length > 0) { - inbind[0].buffer = reinterpret_cast(&client_data[0]); + // If the data happens to be empty, we have to create a 1 byte dummy + // buffer and pass it to the binding. + if (client_data.empty()) { + client_data.resize(1); } + inbind[0].buffer = reinterpret_cast(&client_data[0]); inbind[0].buffer_length = client_data_length; inbind[0].length = &client_data_length; @@ -2027,16 +2046,18 @@ MySqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const { MYSQL_BIND inbind[2]; memset(inbind, 0, sizeof(inbind)); + inbind[0].buffer_type = MYSQL_TYPE_BLOB; + std::vector client_data = clientid.getClientId(); unsigned long client_data_length = client_data.size(); - inbind[0].buffer_type = MYSQL_TYPE_BLOB; - // Only reference the buffer if the buffer has any data. Otherwise - // leave it set to 0 (memset set it to 0 above). - if (client_data_length > 0) { - inbind[0].buffer = reinterpret_cast(&client_data[0]); + // If the data happens to be empty, we have to create a 1 byte dummy + // buffer and pass it to the binding. + if (client_data.empty()) { + client_data.resize(1); } + inbind[0].buffer = reinterpret_cast(&client_data[0]); inbind[0].buffer_length = client_data_length; inbind[0].length = &client_data_length;