Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r49875 - in trunk: boost/date_time boost/date_time/gregorian libs/date_time/src/gregorian libs/date_time/test/gregorian libs/date_time/xmldoc
From: andrey.semashev_at_[hidden]
Date: 2008-11-22 08:40:55


Author: andysem
Date: 2008-11-22 08:40:54 EST (Sat, 22 Nov 2008)
New Revision: 49875
URL: http://svn.boost.org/trac/boost/changeset/49875

Log:
Fixed a possible crash in gregorian::special_value_from_string if the string did not represent a valid special value. The find_match function now accepts the size of lookup tables rater than the maximum index.
Text files modified:
   trunk/boost/date_time/date_parsing.hpp | 15 ++++++++-------
   trunk/boost/date_time/gregorian/greg_facet.hpp | 14 +++++++++-----
   trunk/libs/date_time/src/gregorian/greg_month.cpp | 2 +-
   trunk/libs/date_time/test/gregorian/testdate_input_facet.cpp | 6 ++++++
   trunk/libs/date_time/xmldoc/changes.xml | 8 ++++++++
   5 files changed, 32 insertions(+), 13 deletions(-)

Modified: trunk/boost/date_time/date_parsing.hpp
==============================================================================
--- trunk/boost/date_time/date_parsing.hpp (original)
+++ trunk/boost/date_time/date_parsing.hpp 2008-11-22 08:40:54 EST (Sat, 22 Nov 2008)
@@ -74,22 +74,23 @@
     }
  
     //! Find index of a string in either of 2 arrays
- /*! find_match searches both arrays for a match to 's'. Indexing of the
- * arrays is from 0 to 'limit'. The index of the match is returned.
+ /*! find_match searches both arrays for a match to 's'. Both arrays
+ * must contain 'size' elements. The index of the match is returned.
+ * If no match is found, 'size' is returned.
      * Ex. "Jan" returns 0, "Dec" returns 11, "Tue" returns 2.
- * 'limit' can be sent in with: greg_month::max(),
- * greg_weekday::max() or date_time::NumSpecialValues */
+ * 'size' can be sent in with: greg_month::max() (which 12),
+ * greg_weekday::max() + 1 (which is 7) or date_time::NumSpecialValues */
     template<class charT>
     short find_match(const charT* const* short_names,
                      const charT* const* long_names,
- short limit,
+ short size,
                      const std::basic_string<charT>& s) {
- for(short i = 0; i <= limit; ++i){
+ for(short i = 0; i < size; ++i){
         if(short_names[i] == s || long_names[i] == s){
           return i;
         }
       }
- return static_cast<short>(limit + 1); // not-found, return a value out of range
+ return size; // not-found, return a value out of range
     }
     
     //! Generic function to parse a delimited date (eg: 2002-02-10)

Modified: trunk/boost/date_time/gregorian/greg_facet.hpp
==============================================================================
--- trunk/boost/date_time/gregorian/greg_facet.hpp (original)
+++ trunk/boost/date_time/gregorian/greg_facet.hpp 2008-11-22 08:40:54 EST (Sat, 22 Nov 2008)
@@ -284,7 +284,8 @@
       const facet_def& f = std::use_facet<facet_def>(is.getloc());
       num = date_time::find_match(f.get_short_month_names(),
                                   f.get_long_month_names(),
- (greg_month::max)(), s);
+ (greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size,
+ // which is needed by find_match
     }
     /* bad_cast will be thrown if the desired facet is not accessible
      * so we can generate the facet. This has the drawback of using english
@@ -294,10 +295,11 @@
       std::auto_ptr< const facet_def > f(create_facet_def(a));
       num = date_time::find_match(f->get_short_month_names(),
                                   f->get_long_month_names(),
- (greg_month::max)(), s);
+ (greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size,
+ // which is needed by find_match
     }
     
- num += 1; // months numbered 1-12
+ ++num; // months numbered 1-12
     m = greg_month(num);
 
     return is;
@@ -324,7 +326,8 @@
       const facet_def& f = std::use_facet<facet_def>(is.getloc());
       num = date_time::find_match(f.get_short_weekday_names(),
                                   f.get_long_weekday_names(),
- (greg_weekday::max)(), s);
+ (greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed
+ // to form the array size which is needed by find_match
     }
     /* bad_cast will be thrown if the desired facet is not accessible
      * so we can generate the facet. This has the drawback of using english
@@ -334,7 +337,8 @@
       std::auto_ptr< const facet_def > f(create_facet_def(a));
       num = date_time::find_match(f->get_short_weekday_names(),
                                   f->get_long_weekday_names(),
- (greg_weekday::max)(), s);
+ (greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed
+ // to form the array size which is needed by find_match
     }
    
     wd = greg_weekday(num); // weekdays numbered 0-6

Modified: trunk/libs/date_time/src/gregorian/greg_month.cpp
==============================================================================
--- trunk/libs/date_time/src/gregorian/greg_month.cpp (original)
+++ trunk/libs/date_time/src/gregorian/greg_month.cpp 2008-11-22 08:40:54 EST (Sat, 22 Nov 2008)
@@ -75,7 +75,7 @@
                                     special_value_names,
                                     date_time::NumSpecialValues,
                                     s);
- if(i > date_time::NumSpecialValues) { // match not found
+ if(i >= date_time::NumSpecialValues) { // match not found
       return not_special;
     }
     else {

Modified: trunk/libs/date_time/test/gregorian/testdate_input_facet.cpp
==============================================================================
--- trunk/libs/date_time/test/gregorian/testdate_input_facet.cpp (original)
+++ trunk/libs/date_time/test/gregorian/testdate_input_facet.cpp 2008-11-22 08:40:54 EST (Sat, 22 Nov 2008)
@@ -399,6 +399,12 @@
   check("Special values, default strings, not_a_date_time date",
       d == date(not_a_date_time));
 
+ // in addition check that special_value_from_string also works correctly for other special values
+ check("Special values, default strings, not_special test",
+ special_value_from_string("not_special") == not_special);
+ check("Special values, default strings, junk test",
+ special_value_from_string("junk") == not_special);
+
   // special values custom, strings
   special_values_parser svp("NADT", "MINF", "INF", "MINDT", "MAXDT");
   facet->special_values_parser(svp);

Modified: trunk/libs/date_time/xmldoc/changes.xml
==============================================================================
--- trunk/libs/date_time/xmldoc/changes.xml (original)
+++ trunk/libs/date_time/xmldoc/changes.xml 2008-11-22 08:40:54 EST (Sat, 22 Nov 2008)
@@ -103,6 +103,14 @@
         </row>
 
         <row>
+ <entry>Bug fix</entry>
+ <entry>
+ Fixed a possible crash in <code>gregorian::special_value_from_string</code> if the string
+ did not represent a valid special value.
+ </entry>
+ </row>
+
+ <row>
           <entry>Bug Fix</entry>
           <entry>
           </entry>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk