BIND 10 #2427: support $ORIGIN in dns::MasterLoader

BIND 10 Development do-not-reply at isc.org
Sat Dec 15 06:30:07 UTC 2012


#2427: support $ORIGIN in dns::MasterLoader
-------------------------------------+-------------------------------------
            Reporter:  jinmei        |                        Owner:
                Type:  task          |  jinmei
            Priority:  medium        |                       Status:
           Component:  libdns++      |  reviewing
            Keywords:                |                    Milestone:
           Sensitive:  0             |  Sprint-20121218
         Sub-Project:  DNS           |                   Resolution:
Estimated Difficulty:  3             |                 CVSS Scoring:
         Total Hours:  0             |              Defect Severity:  N/A
                                     |  Feature Depending on Ticket:
                                     |  loadzone-ng
                                     |          Add Hours to Ticket:  0
                                     |                    Internal?:  0
-------------------------------------+-------------------------------------

Comment (by jinmei):

 '''master_loader.cc'''

 - I'd like to avoid using a valid value to mean "not really
   initialized":
 {{{#!cpp
         last_name_(Name::ROOT_NAME()), // Initialize with something,
                                        // we don't care
 }}}
   This will trigger a bug that we see a magical use of root owner name
   through some extension that introduces a case where last_name_ could
   be used before initial explicit set.  I'd suggest something like
   this:
 {{{#!cpp
     scoped_ptr<Name> last_name_;
     ...
     void setLastName(const Name& name) {
         if (!last_name_) {
             last_name_.reset(new Name(name));
         } else {
             *last_name_ = name;
         }
     }
 }}}
   This way, bugs like the one I mentioned above will be detected more
   explicitly and sooner.  This approach will also eliminate the need
   for `seen_name_` (if I understand it correctly).
 - BIND 9 rejects quoted string for $ORIGIN but our current code
   accepts it:
 {{{#!cpp
         // There could be an origin (or maybe not). So try looking
         const MasterToken
 name_tok(lexer_.getNextToken(MasterToken::QSTRING,
                                                        true));
 }}}
   I don't know the rationale of the inconsistency in BIND 9 (asked on
   jabber but no response as of this writing), though.  I quickly had a
   jabber chat with Evan on this, and the tentative conclusion is it's
   an oversight of BIND 9 that allowing qstring for owner name in the
   first place, but it's probably better to keep the behavior if it
   doesn't hurt anyone.  Regarding inconsistency, we seem to tend to
   agree that it's better to be consistent on this, and so allow
   qstring for $ORIGIN value, too.  In the end, we don't have to change
   the implementation, but I suggest documenting the discussion
   explicitly, somewhere.
 - doInclude and doOrigin: it seems implementation-dependent whether to
   allow relative name for $ORIGIN; BIND 9 allows it, NSD doesn't, and
   AFAICS RFC is silent (check yourself).  If it's
   implementation-dependent we should be compatible with BIND 9, so the
   code is okay, but I'd leave a comment about it.
 - Related to the previous point, since there's some non trivial point,
   I'd consider unifying the two cases for ORIGIN even if the code
   block is small.  It seems possible by parameterizing the `eol` param
   of getNextToken().
 - doInclude: name_ok can be a reference:
 {{{#!cpp
         const MasterToken
 name_tok(lexer_.getNextToken(MasterToken::QSTRING,
                                                        true));
 }}}
   (but wouldn't be a big deal as $INCLUDE should be a minor case)

 '''master_loader.cc, loadIncremental()'''

 Now, let's resume the deferred discussion of #2377.  First, I don't
 particularly see it readable, although I'm not saying the BIND 9
 version is more readable.  The `do` loop and the following `if` clause
 are pretty long, greatly reducing the browsability of the main method.
 The double loop due to `do` also makes me use my brain harder to
 figure out what's going on.

 Secondly, we still needed to do ungetToken() (and re-get it) for the
 main scenario.  In case you still misunderstand it, I'm repeating:
 this actually involves redundant data copy.  The effect of this on the
 overall loading overhead may not be significant, but if other points
 are largely comparable, I'd prefer the one that doesn't have this
 overhead.

 There's one other, relatively minor issue in the branch version:
 The use of `MasterToken::NO_TOKEN_PRODUCED`:
 {{{#!cpp
             MasterToken initial_token(MasterToken::NO_TOKEN_PRODUCED);
 }}}
 This is against what the doc says:
 {{{#!cpp
         NO_TOKEN_PRODUCED, ///< No token was produced. This means
 programmer
                            /// error and should never get out of the
 lexer.
 }}}
 We could retroactively distort the description of the value just for
 justifying this particular use, but, in general, such an ad hoc
 semantics change is risky because there can be other part of the code
 that relies on that original design decision.  Even if we don't have
 such an issue for this value, I generally don't like to rely on a
 magic placeholder value just like I explained for last_name_ above.

 I have a counter proposal addressing all of these (or at least
 everything except readability, which, after all, is in the eye of the
 beholder and may vary).  I'm attaching a diff of the proposal.  It
 extracts the handling of the initial token into a separate helper
 method, keeping the main thread concise, avoid using ungetToken() for
 major scenario, and avoid the use of `MasterToken::NO_TOKEN_PRODUCED`.
 It also makes all use of `MasterToken` const.  And, each case for the
 token is completely independent, we can even delegate a part of the
 method if we want further refactoring for even better readability.

 As for readability, I personally think the proposed version is
 measurably more readable, but I admit different people may have
 different impression for this kind of matter.  But at least I'm quite
 sure both versions are largely comparable in readability, and, if so,
 I still much prefer the proposed version because it addresses the
 specific issues I listed above.

 If you think the proposed version makes sense, please make any
 necessary cleanup, etc, and apply it; if you still like the original
 version, we can discuss it, but I'd at least strongly request
 extracting this code logic into a separate method.

 '''master_loader_unittest.cc'''

 - I'd test cases where getNextToken() due to errors, like this one:
 {{{
 $ORIGIN unbalanced)paren
 }}}
 - This case doesn't seem to be tested:
 {{{#!cpp
             } else if (initial_token.getType() == MasterToken::INITIAL_WS)
 {
                 // This means the same name as previous.
                 if (!seen_name_) {
                     isc_throw(InternalException, "No previous name to use
 in "
                               "place of initial whitespace");
                 }
 }}}
 - This case doesn't seem to be tested:
 {{{#!cpp
             } else if (initial_token.getType() == MasterToken::ERROR) {
                 // Error token here.
                 isc_throw(InternalException,
 initial_token.getErrorText());
             } else {
 }}}
 - Does it test trailing garbage after $ORIGIN case?  Also for $INCLUDE +
 origin.
 - Does it test name is bogus for $INCLUDE + origin?
 - One of my comments on #2431 applies: "I'd suggest providing expected
   error message in error_cases like the TTL-related cases do. Invalid
   input could fail in various ways, so if we don't check the actual
   message tests can still pass even if the error is detected in a
   different way than we actually intend."  (But in the case of this
   branch you'd need to rebase it on #2429.)

-- 
Ticket URL: <https://bind10.isc.org/ticket/2427#comment:8>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list