BIND 10 master, updated. eda46b3f2aa8742c7ee7798383d59b401a07bc0f [master] Merge branch 'trac2572-fix'
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Jan 16 16:17:38 UTC 2013
The branch, master has been updated
via eda46b3f2aa8742c7ee7798383d59b401a07bc0f (commit)
via d09c436d4bb61e4ac7e3a6c2f3836ac30b29c40d (commit)
via f45c804082f5ebfbe3339224083531fe86f2bfb2 (commit)
via 5eeb4b30cbea6d0f5588cf0ad542cdccd49510c1 (commit)
via 84ba4a728f827325e262bb91c2517f45efef5d7e (commit)
from c84dafee22cf9c39e1dde4d15c62246ec25fc09a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit eda46b3f2aa8742c7ee7798383d59b401a07bc0f
Merge: c84dafe d09c436
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Wed Jan 16 07:56:53 2013 -0800
[master] Merge branch 'trac2572-fix'
-----------------------------------------------------------------------
Summary of changes:
src/lib/dns/master_lexer.cc | 8 +++++++-
src/lib/dns/master_lexer.h | 16 ++++++++++++++++
src/lib/dns/master_lexer_inputsource.cc | 25 +++++++++++++++++++++----
src/lib/dns/tests/master_lexer_unittest.cc | 9 +++++++++
4 files changed, 53 insertions(+), 5 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dns/master_lexer.cc b/src/lib/dns/master_lexer.cc
index 518bea3..7febd58 100644
--- a/src/lib/dns/master_lexer.cc
+++ b/src/lib/dns/master_lexer.cc
@@ -144,7 +144,13 @@ MasterLexer::pushSource(const char* filename, std::string* error) {
void
MasterLexer::pushSource(std::istream& input) {
- impl_->sources_.push_back(InputSourcePtr(new InputSource(input)));
+ try {
+ impl_->sources_.push_back(InputSourcePtr(new InputSource(input)));
+ } catch (const InputSource::OpenError& ex) {
+ // Convert the "internal" exception to public one.
+ isc_throw(Unexpected, "Failed to push a stream to lexer: " <<
+ ex.what());
+ }
impl_->source_ = impl_->sources_.back().get();
impl_->has_previous_ = false;
impl_->last_was_eol_ = true;
diff --git a/src/lib/dns/master_lexer.h b/src/lib/dns/master_lexer.h
index 9363ff5..d14febe 100644
--- a/src/lib/dns/master_lexer.h
+++ b/src/lib/dns/master_lexer.h
@@ -401,6 +401,22 @@ public:
/// The behavior of the lexer is undefined if the caller builds or adds
/// data in \c input after pushing it.
///
+ /// Except for rare case system errors such as memory allocation failure,
+ /// this method is generally expected to be exception free. However,
+ /// it can still throw if it encounters an unexpected failure when it
+ /// tries to identify the "size" of the input source (see
+ /// \c getTotalSourceSize()). It's an unexpected result unless the
+ /// caller intentionally passes a broken stream; otherwise it would mean
+ /// some system-dependent unexpected behavior or possibly an internal bug.
+ /// In these cases it throws an \c Unexpected exception. Note that
+ /// this version of the method doesn't return a boolean unlike the
+ /// other version that takes a file name; since this failure is really
+ /// unexpected and can be critical, it doesn't make sense to give the
+ /// caller an option to continue (other than by explicitly catching the
+ /// exception).
+ ///
+ /// \throw Unexpected An unexpected failure happens in initialization.
+ ///
/// \param input An input stream object that produces textual
/// representation of DNS RRs.
void pushSource(std::istream& input);
diff --git a/src/lib/dns/master_lexer_inputsource.cc b/src/lib/dns/master_lexer_inputsource.cc
index ec642a2..cc1f505 100644
--- a/src/lib/dns/master_lexer_inputsource.cc
+++ b/src/lib/dns/master_lexer_inputsource.cc
@@ -36,33 +36,50 @@ createStreamName(const std::istream& input_stream) {
size_t
getStreamSize(std::istream& is) {
+ errno = 0; // see below
is.seekg(0, std::ios_base::end);
if (is.bad()) {
// This means the istream has an integrity error. It doesn't make
// sense to continue from this point, so we treat it as a fatal error.
isc_throw(InputSource::OpenError,
"failed to seek end of input source");
- } else if (is.fail()) {
+ } else if (is.fail() || errno != 0) {
// This is an error specific to seekg(). There can be several
// reasons, but the most likely cause in this context is that the
// stream is associated with a special type of file such as a pipe.
// In this case, it's more likely that other main operations of
// the input source work fine, so we continue with just setting
// the stream size to "unknown".
+ //
+ // (At least some versions of) Solaris + SunStudio shows deviant
+ // behavior here: seekg() apparently calls lseek(2) internally, but
+ // even if it fails it doesn't set the error bits of istream. That will
+ // confuse the rest of this function, so, as a heuristic workaround
+ // we check errno and handle any non 0 value as fail().
is.clear(); // clear this error not to confuse later ops.
return (MasterLexer::SOURCE_SIZE_UNKNOWN);
}
const std::streampos len = is.tellg();
+ size_t ret = len;
if (len == static_cast<std::streampos>(-1)) { // cast for some compilers
- isc_throw(InputSource::OpenError, "failed to get input size");
+ if (!is.fail()) {
+ // tellg() returns -1 if istream::fail() would be true, but it's
+ // not guaranteed that it shouldn't be returned in other cases.
+ // In fact, with the combination of SunStudio and stlport,
+ // a stringstream created by the default constructor showed that
+ // behavior. We treat such cases as an unknown size.
+ ret = MasterLexer::SOURCE_SIZE_UNKNOWN;
+ } else {
+ isc_throw(InputSource::OpenError, "failed to get input size");
+ }
}
is.seekg(0, std::ios::beg);
if (is.fail()) {
isc_throw(InputSource::OpenError,
"failed to seek beginning of input source");
}
- assert(len >= 0);
- return (len);
+ assert(len >= 0 || ret == MasterLexer::SOURCE_SIZE_UNKNOWN);
+ return (ret);
}
} // end of unnamed namespace
diff --git a/src/lib/dns/tests/master_lexer_unittest.cc b/src/lib/dns/tests/master_lexer_unittest.cc
index c8ab61f..aececa7 100644
--- a/src/lib/dns/tests/master_lexer_unittest.cc
+++ b/src/lib/dns/tests/master_lexer_unittest.cc
@@ -80,6 +80,15 @@ TEST_F(MasterLexerTest, pushStream) {
checkEmptySource(lexer);
}
+TEST_F(MasterLexerTest, pushStreamFail) {
+ // Pretend a "bad" thing happened in the stream. This will make the
+ // initialization throw an exception.
+ ss << "test";
+ ss.setstate(std::ios_base::badbit);
+
+ EXPECT_THROW(lexer.pushSource(ss), isc::Unexpected);
+}
+
TEST_F(MasterLexerTest, pushFile) {
// We use zone file (-like) data, but in this test that actually doesn't
// matter.
More information about the bind10-changes
mailing list