// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <exceptions/exceptions.h>
+
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/messagerenderer.h>
void
RdataEncoder::addRdata(const rdata::Rdata& rdata) {
+ if (impl_->encode_spec_ == NULL) {
+ isc_throw(InvalidOperation,
+ "RdataEncoder::addRdata performed before start");
+ }
+
impl_->field_composer_.startRdata();
rdata.toWire(impl_->field_composer_);
impl_->field_composer_.endRdata();
size_t
RdataEncoder::getStorageLength() const {
+ if (impl_->encode_spec_ == NULL) {
+ isc_throw(InvalidOperation,
+ "RdataEncoder::getStorageLength performed before start");
+ }
+
return (sizeof(uint16_t) * impl_->field_composer_.data_lengths_.size() +
impl_->field_composer_.getLength());
}
void
RdataEncoder::encode(void* buf, size_t buf_len) const {
- // validation
+ if (impl_->encode_spec_ == NULL) {
+ isc_throw(InvalidOperation,
+ "RdataEncoder::encode performed before start");
+ }
+ if (buf == NULL) {
+ isc_throw(BadValue,
+ "RdataEncoder::encode NULL buffer is given");
+ }
+ if (getStorageLength() > buf_len) {
+ isc_throw(BadValue, "RdataEncoder::encode short buffer given");
+ }
- const uint8_t* const dp_beg = reinterpret_cast<uint8_t*>(buf);
- uint8_t* dp = reinterpret_cast<uint8_t*>(buf);
+ uint8_t* const dp_beg = reinterpret_cast<uint8_t*>(buf);
+ uint8_t* dp = dp_beg;
if (!impl_->field_composer_.data_lengths_.empty()) {
const size_t varlen_fields_len =
impl_->field_composer_.data_lengths_.size() * sizeof(uint16_t);
- uint16_t* lenp = reinterpret_cast<uint16_t*>(buf);
+ uint16_t* const lenp = reinterpret_cast<uint16_t*>(buf);
memcpy(lenp, &impl_->field_composer_.data_lengths_[0],
varlen_fields_len);
dp += varlen_fields_len;
impl_->field_composer_.getLength());
dp += impl_->field_composer_.getLength();
+ // The validation at the entrance must ensure this
assert(buf_len >= dp - dp_beg);
}
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <exceptions/exceptions.h>
+
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/messagerenderer.h>
class RdataEncoderTest : public ::testing::Test {
protected:
- RdataEncoderTest() {}
+ RdataEncoderTest() : a_rdata_(createRdata(RRType::A(), RRClass::IN(),
+ "192.0.2.53"))
+ {}
// This helper test method constructs encodes the given list of RDATAs
// (in rdata_list), and then iterates over the data, rendering the fields
const vector<ConstRdataPtr>& rdata_list,
size_t expected_varlen_fields);
+ const ConstRdataPtr a_rdata_; // commonly used RDATA
RdataEncoder encoder_;
vector<uint8_t> encoded_data_;
MessageRenderer expected_renderer_;
// Four different cases are tested: a single fixed-len RDATA (A),
// fixed-len data + domain name (MX), variable-len data only (TXT),
// variable-len data + domain name (NAPTR).
- ConstRdataPtr a_rdata1 = createRdata(RRType::A(), RRClass::IN(),
- "192.0.2.53");
ConstRdataPtr a_rdata2 = createRdata(RRType::A(), RRClass::IN(),
"192.0.2.54");
rdata_list_.clear();
- rdata_list_.push_back(a_rdata1);
+ rdata_list_.push_back(a_rdata_);
rdata_list_.push_back(a_rdata2);
checkEncode(RRClass::IN(), RRType::A(), rdata_list_, 0);
checkEncode(RRClass::IN(), RRType::NAPTR(), rdata_list_, 1);
}
+TEST_F(RdataEncoderTest, badAddRdata) {
+ // Some operations must follow start().
+ EXPECT_THROW(encoder_.addRdata(*a_rdata_), isc::InvalidOperation);
+ EXPECT_THROW(encoder_.getStorageLength(), isc::InvalidOperation);
+ encoded_data_.resize(256); // allocate space of some arbitrary size
+ EXPECT_THROW(encoder_.encode(&encoded_data_[0], encoded_data_.size()),
+ isc::InvalidOperation);
+
+ // Bad buffer for encode
+ encoder_.start(RRClass::IN(), RRType::A());
+ encoder_.addRdata(*a_rdata_);
+ const size_t buf_len = encoder_.getStorageLength();
+ // NULL buffer for encode
+ EXPECT_THROW(encoder_.encode(NULL, buf_len), isc::BadValue);
+ // buffer length is too short
+ encoded_data_.resize(buf_len - 1);
+ EXPECT_THROW(encoder_.encode(&encoded_data_[0], buf_len - 1),
+ isc::BadValue);
+ encoded_data_.resize(buf_len + 1);
+ encoder_.encode(&encoded_data_[1], buf_len);
+}
+
// TODO: add before start
// Note: in our implementation RRSIG is treated as opaque data (including