$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80887 - in trunk: boost/date_time boost/date_time/posix_time libs/date_time/test/posix_time
From: andrey.semashev_at_[hidden]
Date: 2012-10-06 13:34:06
Author: andysem
Date: 2012-10-06 13:34:06 EDT (Sat, 06 Oct 2012)
New Revision: 80887
URL: http://svn.boost.org/trac/boost/changeset/80887
Log:
Refs #3471. Precompute the duration conversion coefficient to avoid integer overflow. Added a test for integer overflow in the subsecond duration constructor.
Text files modified: 
   trunk/boost/date_time/posix_time/posix_time_config.hpp |     2 +-                                      
   trunk/boost/date_time/time_duration.hpp                |    15 +++++++++++++--                         
   trunk/libs/date_time/test/posix_time/testduration.cpp  |    11 ++++++++++-                             
   3 files changed, 24 insertions(+), 4 deletions(-)
Modified: trunk/boost/date_time/posix_time/posix_time_config.hpp
==============================================================================
--- trunk/boost/date_time/posix_time/posix_time_config.hpp	(original)
+++ trunk/boost/date_time/posix_time/posix_time_config.hpp	2012-10-06 13:34:06 EDT (Sat, 06 Oct 2012)
@@ -81,7 +81,7 @@
     {}
     //Give duration access to ticks constructor -- hide from users
     friend class date_time::time_duration<time_duration, time_res_traits>;
-  private:
+  protected:
     explicit time_duration(impl_type tick_count) :
       date_time::time_duration<time_duration, time_res_traits>(tick_count)
     {}
Modified: trunk/boost/date_time/time_duration.hpp
==============================================================================
--- trunk/boost/date_time/time_duration.hpp	(original)
+++ trunk/boost/date_time/time_duration.hpp	2012-10-06 13:34:06 EDT (Sat, 06 Oct 2012)
@@ -11,6 +11,7 @@
 
 #include <boost/cstdint.hpp>
 #include <boost/operators.hpp>
+#include <boost/static_assert.hpp>
 #include <boost/date_time/time_defs.hpp>
 #include <boost/date_time/special_defs.hpp>
 #include <boost/date_time/compiler_config.hpp>
@@ -265,10 +266,20 @@
   class subsecond_duration : public base_duration
   {
   public:
+    typedef typename base_duration::impl_type impl_type;
     typedef typename base_duration::traits_type traits_type;
+
+  private:
+    // To avoid integer overflow we precompute the duration resolution conversion coefficient (ticket #3471)
+    BOOST_STATIC_ASSERT_MSG((traits_type::ticks_per_second >= frac_of_second ? traits_type::ticks_per_second % frac_of_second : frac_of_second % traits_type::ticks_per_second) == 0,\
+      "The base duration resolution must be a multiple of the subsecond duration resolution");
+    BOOST_STATIC_CONSTANT(boost::int64_t, adjustment_ratio = (traits_type::ticks_per_second >= frac_of_second ? traits_type::ticks_per_second / frac_of_second : frac_of_second / traits_type::ticks_per_second));
+
+  public:
     explicit subsecond_duration(boost::int64_t ss) :
-      base_duration(0,0,0,ss*traits_type::res_adjust()/frac_of_second)
-    {}
+      base_duration(impl_type(traits_type::ticks_per_second >= frac_of_second ? ss * adjustment_ratio : ss / adjustment_ratio))
+    {
+    }
   };
 
 
Modified: trunk/libs/date_time/test/posix_time/testduration.cpp
==============================================================================
--- trunk/libs/date_time/test/posix_time/testduration.cpp	(original)
+++ trunk/libs/date_time/test/posix_time/testduration.cpp	2012-10-06 13:34:06 EDT (Sat, 06 Oct 2012)
@@ -176,7 +176,16 @@
   }
 #endif  
 
-  time_duration t_11(3600,0,0); 
+  // Test for overflows (ticket #3471)
+  {
+    ptime start(boost::gregorian::date(2000, 1, 1));
+    ptime end(boost::gregorian::date(2000, 5, 1));
+    time_duration td = end - start;
+    ptime end2 = start + microseconds(td.total_microseconds());
+    check("microseconds constructor overflow", end == end2);
+  }
+
+  time_duration t_11(3600,0,0);
   check("3600 hours   ",  t_11.hours() == 3600);
   check("total seconds 3600 hours",  t_11.total_seconds() == 12960000);