BIND 10 #2272: Improve the perfdhcp command_options_helper code.

BIND 10 Development do-not-reply at isc.org
Fri Sep 21 17:02:02 UTC 2012


#2272: Improve the perfdhcp command_options_helper code.
-------------------------------------+-------------------------------------
                   Reporter:         |                 Owner:  stephen
  marcin                             |                Status:  reviewing
                       Type:         |             Milestone:  Sprint-
  defect                             |  DHCP-20121004
                   Priority:         |            Resolution:
  medium                             |             Sensitive:  0
                  Component:         |           Sub-Project:  DHCP
  Unclassified                       |  Estimated Difficulty:  0
                   Keywords:         |           Total Hours:  0
            Defect Severity:  N/A    |
Feature Depending on Ticket:         |
        Add Hours to Ticket:  0      |
                  Internal?:  0      |
-------------------------------------+-------------------------------------
Changes (by marcin):

 * owner:  marcin => stephen


Comment:

 Replying to [comment:5 stephen]:
 > Reviewed commit 3148cf2b018b222e263894b80cd7e92b20c86ceb
 >
 > '''configure.ac'''[[BR]]
 > Missing semicolon at the end of the "optreset=1" statement in the
 AC_TRY_LINK code for checking optreset. (Although according to my
 config.log, configure added one anyway.)

 Corrected.

 >
 >
 > '''tests/tools/perfdhcp/tests/command_options_helper.h'''[[BR]]
 > The "results" array allocated is too long: the number of elements in the
 array should not be multiplied by "sizeof(char*)".

 ooops! That looks like typical mistake I make when I replace malloc with
 new.

 >
 > The !CommandOptionsHelper class is only used in unit tests using Gtest.
 With this in mind, when allocating memory with "new", rather than using
 "new (std::nothrow)" then an assert() to check that the returned result is
 non-null, why not write a standard "new" within an EXPECT_NO_THROW?

 That would work as well but my intention was to separate errors that come
 purely from invocation of CommandOptions::parse() from errors that come
 from helper methods, which are only to prepare the input to parse(). If I
 follow your suggestion I would get the error similar to this when new
 fails:

 {{{
 test_control_unittest.cc:633: Failure
 Expected: processCmdLine("perfdhcp -l 127.0.0.1 all") doesn't throw an
 exception.
   Actual: it throws.
 }}}

 which tells me nothing where the error comes from and since failure to
 allocate memory with new would be very rare, my intuition would tell me
 that it is exception produced by CommandOptions::parse (which would not be
 true). Apart from this all tests will be run and each will end be
 interrupted by ASSERT_NO_THROW because it is unlikely that if allocation
 issue occurs for the first time it will not occur later.

 If I leave as it is now, I get:
 {{{
 lt-run_unittests: command_options_helper.h:119: static char**
 isc::perfdhcp::CommandOptionsHelper::tokenizeString(const string&, int&):
 Assertion `results == __null' failed.
 }}}

 and I immediately know that it is the error in helper function, not in the
 tested class. In addition unit testing breaks (and I belive it should) as
 this is a fatal error.

 >
 >
 > '''tests/tools/perfdhcp/tests/command_options_helper.cc'''[[BR]]
 > > There are at least two ways to reset the state of the getopt() to
 prevent it from trying to access freed buffers. On Linux: the optind must
 be set to 0. This however does not work on BSD and MacOS where there is an
 additional variable declared: optreset. On those systems both optreset and
 optind must be set to 1.
 > This seems to imply that both optind and optreset must be set to 1 on
 BSD systems only (i.e. with HAVE_OPTRESET set to 1).  However the code
 only sets optreset according to this preprocessor symbol; the setting of
 optind is determined by the macro !__GLIBC!__.

 I am not sure if I understand the comment.
 If HAVE_OPTRESET is defined it means that optreset variable exists and I
 can set it. If it is undefined I can't set it. If it exists the only value
 I should set it to is 1 (there is no other value I should be setting it
 to). I don't set optind in HAVE_OPTRESET clause because I am setting it if
 GLIBC is undefined. If I am working on BSD the GLIBC will be undefined
 which means that optind will be set to 1, then optreset set to 1 which is
 what I want. If GLIBC is there the optind must be set to 0 and then there
 is no HAVE_OPTRESET because GLIBC does not need optreset (because it
 resets through optind=0). I think, this code is going to work in each
 case.

-- 
Ticket URL: <http://bind10.isc.org/ticket/2272#comment:6>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list