Fix a subtle bug in UCI options printing
authorMarco Costalba <mcostalba@gmail.com>
Sat, 22 Mar 2014 10:15:28 +0000 (11:15 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sat, 22 Mar 2014 10:30:06 +0000 (11:30 +0100)
commit4eee60343323499d087709614d47e24f66437697
treec55bc0d3703f537d466af204bdb90bd73807df37
parentc714b90594cb7ec1fc9635c6e9abb15cef6d7095
Fix a subtle bug in UCI options printing

We want all the UCI options are printed in the order in which are
assigned, so we use an index that, depending on Options.size(),
increases after each option is added to the map. The problem is
that, for instance, in the first assignment:

o["Write Debug Log"] = Option(false, on_logger);

Options.size() can value 0 or 1 according if the l-value (that
increments the size) has been evaluated after or before the
r-value (that uses the size value).

The culprit is that assignment operator in C++ is not a
sequence point:

http://en.wikipedia.org/wiki/Sequence_point

(Note: to be nitpick here we actually use std::map::operator=()
 that being a function can evaluate its arguments in any order)

So there is no guarantee on what term is evaluated first and
behavior is undefined by standard in this case. The net result
is that in case r-value is evaluated after l-value the last
idx is not size() - 1, but size() and in the printing loop
we miss the last option!

Bug was there since ages but only recently has been exposed by
the removal of UCI_Analyze option so that the last one becomes
UCI_Chess960 and when it is missing engine cannot play anymore
Chess960.

The fix is trivial (although a bit hacky): just increase the
last loop index.

Reported by Eric Mullins that found it on an ARM and MIPS
platforms with gcc 4.7

No functional change.
src/ucioption.cpp