Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: base/time/time_posix.cc

Issue 2405453002: Fix Integer-overflow in base::Time::FromExploded. (Closed)
Patch Set: move method under ifdef Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/time/time.h" 5 #include "base/time/time.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <sys/time.h> 8 #include <sys/time.h>
9 #include <time.h> 9 #include <time.h>
10 #if defined(OS_ANDROID) && !defined(__LP64__) 10 #if defined(OS_ANDROID) && !defined(__LP64__)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 struct timespec ts; 106 struct timespec ts;
107 if (clock_gettime(clk_id, &ts) != 0) { 107 if (clock_gettime(clk_id, &ts) != 0) {
108 NOTREACHED() << "clock_gettime(" << clk_id << ") failed."; 108 NOTREACHED() << "clock_gettime(" << clk_id << ") failed.";
109 return 0; 109 return 0;
110 } 110 }
111 return ConvertTimespecToMicros(ts); 111 return ConvertTimespecToMicros(ts);
112 } 112 }
113 #else // _POSIX_MONOTONIC_CLOCK 113 #else // _POSIX_MONOTONIC_CLOCK
114 #error No usable tick clock function on this platform. 114 #error No usable tick clock function on this platform.
115 #endif // _POSIX_MONOTONIC_CLOCK 115 #endif // _POSIX_MONOTONIC_CLOCK
116
117 // Safely multiplies |init_value| by |multiply_value| and adds |add_value|
118 // to that. Returns result or 0 value avoiding overflows.
119 int64_t MultiplyAndAdd(int64_t init_value,
miu 2016/10/18 19:55:13 This helper hides whether overflow occurs (i.e., i
maksims (do not use this acc) 2016/10/19 16:41:04 Removed
120 int64_t multiply_value,
121 int64_t add_value) {
122 base::CheckedNumeric<int64_t> result(init_value);
123 result *= multiply_value;
124 result += add_value;
125 return result.ValueOrDefault(0);
126 }
127
116 #endif // !defined(OS_MACOSX) 128 #endif // !defined(OS_MACOSX)
117 129
118 } // namespace 130 } // namespace
119 131
120 namespace base { 132 namespace base {
121 133
122 // static 134 // static
123 TimeDelta TimeDelta::FromTimeSpec(const timespec& ts) { 135 TimeDelta TimeDelta::FromTimeSpec(const timespec& ts) {
124 return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond + 136 return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
125 ts.tv_nsec / Time::kNanosecondsPerMicrosecond); 137 ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 timestruct.tm_mon = exploded.month - 1; 247 timestruct.tm_mon = exploded.month - 1;
236 timestruct.tm_year = exploded.year - 1900; 248 timestruct.tm_year = exploded.year - 1900;
237 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this 249 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this
238 timestruct.tm_yday = 0; // mktime/timegm ignore this 250 timestruct.tm_yday = 0; // mktime/timegm ignore this
239 timestruct.tm_isdst = -1; // attempt to figure it out 251 timestruct.tm_isdst = -1; // attempt to figure it out
240 #if !defined(OS_NACL) && !defined(OS_SOLARIS) 252 #if !defined(OS_NACL) && !defined(OS_SOLARIS)
241 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore 253 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore
242 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore 254 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore
243 #endif 255 #endif
244 256
245 int64_t milliseconds; 257 int64_t milliseconds = 0;
miu 2016/10/18 19:55:13 nit: Please move the declaration of |milliseconds|
maksims (do not use this acc) 2016/10/19 16:41:04 Done.
246 SysTime seconds; 258 SysTime seconds;
247 259
248 // Certain exploded dates do not really exist due to daylight saving times, 260 // Certain exploded dates do not really exist due to daylight saving times,
249 // and this causes mktime() to return implementation-defined values when 261 // and this causes mktime() to return implementation-defined values when
250 // tm_isdst is set to -1. On Android, the function will return -1, while the 262 // tm_isdst is set to -1. On Android, the function will return -1, while the
251 // C libraries of other platforms typically return a liberally-chosen value. 263 // C libraries of other platforms typically return a liberally-chosen value.
252 // Handling this requires the special code below. 264 // Handling this requires the special code below.
253 265
254 // SysTimeFromTimeStruct() modifies the input structure, save current value. 266 // SysTimeFromTimeStruct() modifies the input structure, save current value.
255 struct tm timestruct0 = timestruct; 267 struct tm timestruct0 = timestruct;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t)) 317 const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t))
306 ? std::numeric_limits<SysTime>::max() 318 ? std::numeric_limits<SysTime>::max()
307 : std::numeric_limits<int32_t>::max(); 319 : std::numeric_limits<int32_t>::max();
308 if (exploded.year < 1969) { 320 if (exploded.year < 1969) {
309 milliseconds = min_seconds * kMillisecondsPerSecond; 321 milliseconds = min_seconds * kMillisecondsPerSecond;
310 } else { 322 } else {
311 milliseconds = max_seconds * kMillisecondsPerSecond; 323 milliseconds = max_seconds * kMillisecondsPerSecond;
312 milliseconds += (kMillisecondsPerSecond - 1); 324 milliseconds += (kMillisecondsPerSecond - 1);
313 } 325 }
314 } else { 326 } else {
315 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; 327 milliseconds =
miu 2016/10/18 19:55:13 Suggestion (to return false if overflow occurs):
maksims (do not use this acc) 2016/10/19 16:41:04 Done.
328 MultiplyAndAdd(seconds, kMillisecondsPerSecond, exploded.millisecond);
316 } 329 }
317 330
318 // Adjust from Unix (1970) to Windows (1601) epoch. 331 // Adjust from Unix (1970) to Windows (1601) epoch.
319 base::Time converted_time = 332 int64_t microseconds_win_epoch =
miu 2016/10/18 19:55:13 Similar suggestion here: Declare |microseconds_win
maksims (do not use this acc) 2016/10/19 16:41:04 Done.
320 Time((milliseconds * kMicrosecondsPerMillisecond) + 333 MultiplyAndAdd(milliseconds, kMicrosecondsPerMillisecond,
321 kWindowsEpochDeltaMicroseconds); 334 kWindowsEpochDeltaMicroseconds);
335 base::Time converted_time(microseconds_win_epoch);
322 336
323 // If |exploded.day_of_month| is set to 31 on a 28-30 day month, it will 337 // If |exploded.day_of_month| is set to 31 on a 28-30 day month, it will
324 // return the first day of the next month. Thus round-trip the time and 338 // return the first day of the next month. Thus round-trip the time and
325 // compare the initial |exploded| with |utc_to_exploded| time. 339 // compare the initial |exploded| with |utc_to_exploded| time.
326 base::Time::Exploded to_exploded; 340 base::Time::Exploded to_exploded;
327 if (!is_local) 341 if (!is_local)
328 converted_time.UTCExplode(&to_exploded); 342 converted_time.UTCExplode(&to_exploded);
329 else 343 else
330 converted_time.LocalExplode(&to_exploded); 344 converted_time.LocalExplode(&to_exploded);
331 345
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; 411 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
398 return result; 412 return result;
399 } 413 }
400 int64_t us = us_ - kTimeTToMicrosecondsOffset; 414 int64_t us = us_ - kTimeTToMicrosecondsOffset;
401 result.tv_sec = us / Time::kMicrosecondsPerSecond; 415 result.tv_sec = us / Time::kMicrosecondsPerSecond;
402 result.tv_usec = us % Time::kMicrosecondsPerSecond; 416 result.tv_usec = us % Time::kMicrosecondsPerSecond;
403 return result; 417 return result;
404 } 418 }
405 419
406 } // namespace base 420 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698