Commit f26298e3 authored by Jelte Jansen's avatar Jelte Jansen

[master] Merge branch 'trac1160'

Conflicts:
	src/lib/dns/rdata/in_1/srv_33.cc
parents c5124556 7489fa47
......@@ -56,6 +56,7 @@ EXTRA_DIST += auth_messages.mes
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
b10_auth_LDADD += $(top_builddir)/src/lib/util/libutil.la
b10_auth_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -17,6 +17,7 @@ query_bench_SOURCES += ../auth_log.h ../auth_log.cc
nodist_query_bench_SOURCES = ../auth_messages.h ../auth_messages.cc
query_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
query_bench_LDADD += $(top_builddir)/src/lib/util/libutil.la
query_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
query_bench_LDADD += $(top_builddir)/src/lib/bench/libbench.la
query_bench_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
......
......@@ -47,6 +47,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
......
......@@ -35,6 +35,7 @@ b10_dhcp6_SOURCES = main.cc
b10_dhcp6_SOURCES += dhcp6.h
b10_dhcp6_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/util/libutil.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -13,6 +13,7 @@ CLEANFILES = *.gcno *.gcda
bin_PROGRAMS = b10-host
b10_host_SOURCES = host.cc
b10_host_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
b10_host_LDADD += $(top_builddir)/src/lib/util/libutil.la
b10_host_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
man_MANS = b10-host.1
......
......@@ -16,6 +16,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(top_builddir)/src/lib/bench/libbench.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(GTEST_LDADD)
......
......@@ -56,6 +56,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/cache/libcache.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -36,6 +36,7 @@ run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
......
......@@ -13,5 +13,6 @@ noinst_PROGRAMS = rdatarender_bench
rdatarender_bench_SOURCES = rdatarender_bench.cc
rdatarender_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
rdatarender_bench_LDADD += $(top_builddir)/src/lib/util/libutil.la
rdatarender_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
rdatarender_bench_LDADD += $(SQLITE_LIBS)
......@@ -19,6 +19,7 @@
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/strutil.h>
#include <util/encode/base64.h>
#include <dns/messagerenderer.h>
......@@ -30,6 +31,7 @@ using namespace std;
using namespace boost;
using namespace isc::util;
using namespace isc::util::encode;
using namespace isc::util::str;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
......@@ -65,45 +67,6 @@ struct TSIG::TSIGImpl {
const vector<uint8_t> other_data_;
};
namespace {
string
getToken(istringstream& iss, const string& full_input) {
string token;
iss >> token;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid TSIG text: parse error " <<
full_input);
}
return (token);
}
// This helper function converts a string token to an *unsigned* integer.
// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
// wide to store resulting integers.
// BitSize is the maximum number of bits that the resulting integer can take.
// This function first checks whether the given token can be converted to
// an integer of NumType type. It then confirms the conversion result is
// within the valid range, i.e., [0, 2^NumType - 1]. The second check is
// necessary because lexical_cast<T> where T is an unsigned integer type
// doesn't correctly reject negative numbers when compiled with SunStudio.
template <typename NumType, int BitSize>
NumType
tokenToNum(const string& num_token) {
NumType num;
try {
num = lexical_cast<NumType>(num_token);
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(InvalidRdataText, "Invalid TSIG numeric parameter: " <<
num_token);
}
if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
isc_throw(InvalidRdataText, "Numeric TSIG parameter out of range: " <<
num);
}
return (num);
}
}
/// \brief Constructor from string.
///
/// \c tsig_str must be formatted as follows:
......@@ -148,47 +111,52 @@ tokenToNum(const string& num_token) {
TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) {
istringstream iss(tsig_str);
const Name algorithm(getToken(iss, tsig_str));
const int64_t time_signed = tokenToNum<int64_t, 48>(getToken(iss,
tsig_str));
const int32_t fudge = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const int32_t macsize = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const string mac_txt = (macsize > 0) ? getToken(iss, tsig_str) : "";
vector<uint8_t> mac;
decodeBase64(mac_txt, mac);
if (mac.size() != macsize) {
isc_throw(InvalidRdataText, "TSIG MAC size and data are inconsistent");
}
const int32_t orig_id = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const string error_txt = getToken(iss, tsig_str);
int32_t error = 0;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if (error_txt == "BADSIG") {
error = 16;
} else if (error_txt == "BADKEY") {
error = 17;
} else if (error_txt == "BADTIME") {
error = 18;
} else {
error = tokenToNum<int32_t, 16>(error_txt);
}
const int32_t otherlen = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const string otherdata_txt = (otherlen > 0) ? getToken(iss, tsig_str) : "";
vector<uint8_t> other_data;
decodeBase64(otherdata_txt, other_data);
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for TSIG RDATA: " <<
tsig_str);
try {
const Name algorithm(getToken(iss));
const int64_t time_signed = tokenToNum<int64_t, 48>(getToken(iss));
const int32_t fudge = tokenToNum<int32_t, 16>(getToken(iss));
const int32_t macsize = tokenToNum<int32_t, 16>(getToken(iss));
const string mac_txt = (macsize > 0) ? getToken(iss) : "";
vector<uint8_t> mac;
decodeBase64(mac_txt, mac);
if (mac.size() != macsize) {
isc_throw(InvalidRdataText, "TSIG MAC size and data are inconsistent");
}
const int32_t orig_id = tokenToNum<int32_t, 16>(getToken(iss));
const string error_txt = getToken(iss);
int32_t error = 0;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if (error_txt == "BADSIG") {
error = 16;
} else if (error_txt == "BADKEY") {
error = 17;
} else if (error_txt == "BADTIME") {
error = 18;
} else {
error = tokenToNum<int32_t, 16>(error_txt);
}
const int32_t otherlen = tokenToNum<int32_t, 16>(getToken(iss));
const string otherdata_txt = (otherlen > 0) ? getToken(iss) : "";
vector<uint8_t> other_data;
decodeBase64(otherdata_txt, other_data);
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for TSIG RDATA: " <<
tsig_str);
}
impl_ = new TSIGImpl(algorithm, time_signed, fudge, mac, orig_id,
error, other_data);
} catch (StringTokenError ste) {
isc_throw(InvalidRdataText, "Invalid TSIG text: " << ste.what() <<
": " << tsig_str);
}
impl_ = new TSIGImpl(algorithm, time_signed, fudge, mac, orig_id,
error, other_data);
}
/// \brief Constructor from wire-format data.
......
......@@ -18,6 +18,7 @@
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/strutil.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
......@@ -26,6 +27,7 @@
using namespace std;
using namespace isc::util;
using namespace isc::util::str;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
......@@ -44,39 +46,6 @@ struct SRVImpl {
Name target_;
};
namespace {
string
getToken(istringstream& iss, const string& full_input) {
string token;
iss >> token;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid SRV text: parse error " <<
full_input);
}
return (token);
}
// This helper function converts a string token to an *unsigned* integer.
// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
// wide to store resulting integers.
template <typename NumType, int BitSize>
NumType
tokenToNum(const string& num_token) {
NumType num;
try {
num = boost::lexical_cast<NumType>(num_token);
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(InvalidRdataText, "Invalid SRV numeric parameter: " <<
num_token);
}
if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
isc_throw(InvalidRdataText, "Numeric SRV parameter out of range: " <<
num);
}
return (num);
}
}
/// \brief Constructor from string.
///
/// \c srv_str must be formatted as follows:
......@@ -103,17 +72,22 @@ SRV::SRV(const string& srv_str) :
{
istringstream iss(srv_str);
const int32_t priority = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
const int32_t weight = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
const int32_t port = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
const Name targetname(getToken(iss, srv_str));
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for SRV RDATA: " <<
srv_str);
try {
const int32_t priority = tokenToNum<int32_t, 16>(getToken(iss));
const int32_t weight = tokenToNum<int32_t, 16>(getToken(iss));
const int32_t port = tokenToNum<int32_t, 16>(getToken(iss));
const Name targetname(getToken(iss));
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for SRV RDATA: " <<
srv_str);
}
impl_ = new SRVImpl(priority, weight, port, targetname);
} catch (StringTokenError ste) {
isc_throw(InvalidRdataText, "Invalid SRV text: " <<
ste.what() << ": " << srv_str);
}
impl_ = new SRVImpl(priority, weight, port, targetname);
}
/// \brief Constructor from wire-format data.
......
......@@ -31,6 +31,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
run_unittests_LDADD += $(top_builddir)/src/lib/resolve/libresolve.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -132,6 +132,17 @@ format(const std::string& format, const std::vector<std::string>& args) {
return (result);
}
std::string
getToken(std::istringstream& iss) {
string token;
iss >> token;
if (iss.bad() || iss.fail()) {
isc_throw(StringTokenError, "could not read token from string");
}
return (token);
}
} // namespace str
} // namespace util
} // namespace isc
......@@ -18,7 +18,10 @@
#include <algorithm>
#include <cctype>
#include <string>
#include <sstream>
#include <vector>
#include <exceptions/exceptions.h>
#include <boost/lexical_cast.hpp>
namespace isc {
namespace util {
......@@ -26,6 +29,16 @@ namespace str {
/// \brief A Set of C++ Utilities for Manipulating Strings
///
/// \brief A standard string util exception that is thrown if getToken or
/// numToToken are called with bad input data
///
class StringTokenError : public Exception {
public:
StringTokenError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// \brief Normalize Backslash
///
/// Only relevant to Windows, this replaces all "\" in a string with "/" and
......@@ -140,6 +153,55 @@ std::string format(const std::string& format,
const std::vector<std::string>& args);
/// \brief Returns one token from the given stringstream
///
/// Using the >> operator, with basic error checking
///
/// \exception StringTokenError if the token cannot be read from the stream
///
/// \param iss stringstream to read one token from
///
/// \return the first token read from the stringstream
std::string getToken(std::istringstream& iss);
/// \brief Converts a string token to an *unsigned* integer.
///
/// The value is converted using a lexical cast, with error and bounds
/// checking.
///
/// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
/// wide to store resulting integers.
///
/// BitSize is the maximum number of bits that the resulting integer can take.
/// This function first checks whether the given token can be converted to
/// an integer of NumType type. It then confirms the conversion result is
/// within the valid range, i.e., [0, 2^BitSize - 1]. The second check is
/// necessary because lexical_cast<T> where T is an unsigned integer type
/// doesn't correctly reject negative numbers when compiled with SunStudio.
///
/// \exception StringTokenError if the value is out of range, or if it
/// could not be converted
///
/// \param num_token the string token to convert
///
/// \return the converted value, of type NumType
template <typename NumType, int BitSize>
NumType
tokenToNum(const std::string& num_token) {
NumType num;
try {
num = boost::lexical_cast<NumType>(num_token);
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(StringTokenError, "Invalid SRV numeric parameter: " <<
num_token);
}
if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
isc_throw(StringTokenError, "Numeric SRV parameter out of range: " <<
num);
}
return (num);
}
} // namespace str
} // namespace util
} // namespace isc
......
......@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <stdint.h>
#include <string>
#include <gtest/gtest.h>
......@@ -22,17 +24,9 @@ using namespace isc;
using namespace isc::util;
using namespace std;
class StringUtilTest : public ::testing::Test {
protected:
StringUtilTest()
{
}
};
// Check for slash replacement
TEST_F(StringUtilTest, Slash) {
TEST(StringUtilTest, Slash) {
string instring = "";
isc::util::str::normalizeSlash(instring);
......@@ -49,7 +43,7 @@ TEST_F(StringUtilTest, Slash) {
// Check that leading and trailing space trimming works
TEST_F(StringUtilTest, Trim) {
TEST(StringUtilTest, Trim) {
// Empty and full string.
EXPECT_EQ("", isc::util::str::trim(""));
......@@ -71,7 +65,7 @@ TEST_F(StringUtilTest, Trim) {
// returned vector; if not as expected, the following references may be invalid
// so should not be used.
TEST_F(StringUtilTest, Tokens) {
TEST(StringUtilTest, Tokens) {
vector<string> result;
// Default delimiters
......@@ -157,7 +151,7 @@ TEST_F(StringUtilTest, Tokens) {
// Changing case
TEST_F(StringUtilTest, ChangeCase) {
TEST(StringUtilTest, ChangeCase) {
string mixed("abcDEFghiJKLmno123[]{=+--+]}");
string upper("ABCDEFGHIJKLMNO123[]{=+--+]}");
string lower("abcdefghijklmno123[]{=+--+]}");
......@@ -173,7 +167,7 @@ TEST_F(StringUtilTest, ChangeCase) {
// Formatting
TEST_F(StringUtilTest, Formatting) {
TEST(StringUtilTest, Formatting) {
vector<string> args;
args.push_back("arg1");
......@@ -213,3 +207,63 @@ TEST_F(StringUtilTest, Formatting) {
string format9 = "%s %s";
EXPECT_EQ(format9, isc::util::str::format(format9, args));
}
TEST(StringUtilTest, getToken) {
string s("a b c");
istringstream ss(s);
EXPECT_EQ("a", isc::util::str::getToken(ss));
EXPECT_EQ("b", isc::util::str::getToken(ss));
EXPECT_EQ("c", isc::util::str::getToken(ss));
EXPECT_THROW(isc::util::str::getToken(ss), isc::util::str::StringTokenError);
}
int32_t tokenToNumCall_32_16(const string& token) {
return isc::util::str::tokenToNum<int32_t, 16>(token);
}
int16_t tokenToNumCall_16_8(const string& token) {
return isc::util::str::tokenToNum<int16_t, 8>(token);
}
TEST(StringUtilTest, tokenToNum) {
uint32_t num32 = tokenToNumCall_32_16("0");
EXPECT_EQ(0, num32);
num32 = tokenToNumCall_32_16("123");
EXPECT_EQ(123, num32);
num32 = tokenToNumCall_32_16("65535");
EXPECT_EQ(65535, num32);
EXPECT_THROW(tokenToNumCall_32_16(""),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_32_16("a"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_32_16("-1"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_32_16("65536"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_32_16("1234567890"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_32_16("-1234567890"),
isc::util::str::StringTokenError);
uint16_t num16 = tokenToNumCall_16_8("123");
EXPECT_EQ(123, num16);
num16 = tokenToNumCall_16_8("0");
EXPECT_EQ(0, num16);
num16 = tokenToNumCall_16_8("255");
EXPECT_EQ(255, num16);
EXPECT_THROW(tokenToNumCall_16_8(""),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_16_8("a"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_16_8("-1"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_16_8("256"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_16_8("1234567890"),
isc::util::str::StringTokenError);
EXPECT_THROW(tokenToNumCall_16_8("-1234567890"),
isc::util::str::StringTokenError);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment