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

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

Issue 27472003: android: fix base::Time::FromLocalExploded() crash. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git cl try Created 7 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
« no previous file with comments | « no previous file | base/time/time_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) 10 #if defined(OS_ANDROID)
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 timestruct.tm_mon = exploded.month - 1; 207 timestruct.tm_mon = exploded.month - 1;
208 timestruct.tm_year = exploded.year - 1900; 208 timestruct.tm_year = exploded.year - 1900;
209 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this 209 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this
210 timestruct.tm_yday = 0; // mktime/timegm ignore this 210 timestruct.tm_yday = 0; // mktime/timegm ignore this
211 timestruct.tm_isdst = -1; // attempt to figure it out 211 timestruct.tm_isdst = -1; // attempt to figure it out
212 #if !defined(OS_NACL) && !defined(OS_SOLARIS) 212 #if !defined(OS_NACL) && !defined(OS_SOLARIS)
213 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore 213 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore
214 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore 214 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore
215 #endif 215 #endif
216 216
217 SysTime seconds = SysTimeFromTimeStruct(&timestruct, is_local);
218 217
219 int64 milliseconds; 218 int64 milliseconds;
219 SysTime seconds;
220
221 #if defined(OS_ANDROID)
jar (doing other things) 2013/10/18 02:14:17 This probably isn't an android only problem. It r
digit1 2013/10/18 08:54:59 Thanks, I've remove the #if defined(OS_ANDROID) no
222 // Certain exploded dates do not really exist due to daylight saving times,
223 // and this causes mktime() to return implementation-defined values when
224 // tm_isdst is set to -1. On Android, the function will return -1, while the
225 // C libraries of other platforms typically return a liberally chosen value.
226 // Handling this requires the special code below.
227
228 // SysTimeFromTimeStruct() modifies the input structure, save current value.
229 struct tm timestruct0 = timestruct;
230
231 seconds = SysTimeFromTimeStruct(&timestruct, is_local);
232 if (seconds == -1) {
233 // Get the time values with tm_isdst == 0 and 1, then select the closest one
234 // to UTC 00:00:00 that isn't -1.
235 timestruct = timestruct0;
236 timestruct.tm_isdst = 0;
237 int64 seconds_isdst0 = SysTimeFromTimeStruct(&timestruct, is_local);
238
239 timestruct = timestruct0;
240 timestruct.tm_isdst = 1;
241 int64 seconds_isdst1 = SysTimeFromTimeStruct(&timestruct, is_local);
242
243 // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones.
244 // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'.
245 if (seconds_isdst0 < 0)
246 seconds = seconds_isdst1;
247 else if (seconds_isdst1 < 0)
248 seconds = seconds_isdst0;
249 else
250 seconds = std::min(seconds_isdst0, seconds_isdst1);
251 }
252 #else
253 seconds = SysTimeFromTimeStruct(&timestruct, is_local);
254 #endif
255
220 // Handle overflow. Clamping the range to what mktime and timegm might 256 // Handle overflow. Clamping the range to what mktime and timegm might
221 // return is the best that can be done here. It's not ideal, but it's better 257 // return is the best that can be done here. It's not ideal, but it's better
222 // than failing here or ignoring the overflow case and treating each time 258 // than failing here or ignoring the overflow case and treating each time
223 // overflow as one second prior to the epoch. 259 // overflow as one second prior to the epoch.
224 if (seconds == -1 && 260 if (seconds == -1 &&
225 (exploded.year < 1969 || exploded.year > 1970)) { 261 (exploded.year < 1969 || exploded.year > 1970)) {
226 // If exploded.year is 1969 or 1970, take -1 as correct, with the 262 // If exploded.year is 1969 or 1970, take -1 as correct, with the
227 // time indicating 1 second prior to the epoch. (1970 is allowed to handle 263 // time indicating 1 second prior to the epoch. (1970 is allowed to handle
228 // time zone and DST offsets.) Otherwise, return the most future or past 264 // time zone and DST offsets.) Otherwise, return the most future or past
229 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. 265 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC.
230 // 266 //
231 // The minimum and maximum representible times that mktime and timegm could 267 // The minimum and maximum representible times that mktime and timegm could
232 // return are used here instead of values outside that range to allow for 268 // return are used here instead of values outside that range to allow for
233 // proper round-tripping between exploded and counter-type time 269 // proper round-tripping between exploded and counter-type time
234 // representations in the presence of possible truncation to time_t by 270 // representations in the presence of possible truncation to time_t by
235 // division and use with other functions that accept time_t. 271 // division and use with other functions that accept time_t.
236 // 272 //
237 // When representing the most distant time in the future, add in an extra 273 // When representing the most distant time in the future, add in an extra
238 // 999ms to avoid the time being less than any other possible value that 274 // 999ms to avoid the time being less than any other possible value that
239 // this function can return. 275 // this function can return.
276
277 // On Android, SysTime is int64, special care must be taken to avoid
278 // overflows.
279 const int64 min_seconds = (sizeof(SysTime) < sizeof(int64))
280 ? std::numeric_limits<SysTime>::min()
281 : std::numeric_limits<int32_t>::min();
282 const int64 max_seconds = (sizeof(SysTime) < sizeof(int64))
283 ? std::numeric_limits<SysTime>::max()
284 : std::numeric_limits<int32_t>::max();
240 if (exploded.year < 1969) { 285 if (exploded.year < 1969) {
241 CHECK(sizeof(SysTime) < sizeof(int64)) << "integer overflow"; 286 milliseconds = min_seconds * kMillisecondsPerSecond;
242 milliseconds = std::numeric_limits<SysTime>::min();
243 milliseconds *= kMillisecondsPerSecond;
244 } else { 287 } else {
245 CHECK(sizeof(SysTime) < sizeof(int64)) << "integer overflow"; 288 milliseconds = max_seconds * kMillisecondsPerSecond;
246 milliseconds = std::numeric_limits<SysTime>::max();
247 milliseconds *= kMillisecondsPerSecond;
248 milliseconds += (kMillisecondsPerSecond - 1); 289 milliseconds += (kMillisecondsPerSecond - 1);
249 } 290 }
250 } else { 291 } else {
251 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; 292 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond;
252 } 293 }
253 294
254 // Adjust from Unix (1970) to Windows (1601) epoch. 295 // Adjust from Unix (1970) to Windows (1601) epoch.
255 return Time((milliseconds * kMicrosecondsPerMillisecond) + 296 return Time((milliseconds * kMicrosecondsPerMillisecond) +
256 kWindowsEpochDeltaMicroseconds); 297 kWindowsEpochDeltaMicroseconds);
257 } 298 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; 384 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
344 return result; 385 return result;
345 } 386 }
346 int64 us = us_ - kTimeTToMicrosecondsOffset; 387 int64 us = us_ - kTimeTToMicrosecondsOffset;
347 result.tv_sec = us / Time::kMicrosecondsPerSecond; 388 result.tv_sec = us / Time::kMicrosecondsPerSecond;
348 result.tv_usec = us % Time::kMicrosecondsPerSecond; 389 result.tv_usec = us % Time::kMicrosecondsPerSecond;
349 return result; 390 return result;
350 } 391 }
351 392
352 } // namespace base 393 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | base/time/time_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698