Skip to content

Commit

Permalink
Merge pull request #6591 from jmdavis/issue_17732_again
Browse files Browse the repository at this point in the history
Fix issue 12507: SysTime.init.toString() segfaults.
merged-on-behalf-of: Petar Kirov <ZombineDev@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Jun 26, 2018
2 parents 0de75ca + 9b1f72d commit ec8bb20
Showing 1 changed file with 94 additions and 9 deletions.
103 changes: 94 additions & 9 deletions std/datetime/systime.d
Expand Up @@ -2003,7 +2003,14 @@ public:
@property bool dstInEffect() @safe const nothrow
{
return _timezone.dstInEffect(_stdTime);
// This function's unit testing is done in the time zone classes.
}

// This function's full unit testing is done in the time zone classes, but
// this verifies that SysTime.init works correctly, since historically, it
// has segfaulted due to a null _timezone.
@safe unittest
{
assert(!SysTime.init.dstInEffect);
}


Expand All @@ -2016,6 +2023,14 @@ public:
return _timezone.utcOffsetAt(_stdTime);
}

// This function's full unit testing is done in the time zone classes, but
// this verifies that SysTime.init works correctly, since historically, it
// has segfaulted due to a null _timezone.
@safe unittest
{
assert(SysTime.init.utcOffset == Duration.zero);
}


/++
Returns a $(LREF SysTime) with the same std time as this one, but with
Expand Down Expand Up @@ -2342,7 +2357,7 @@ public:
{
import std.utf : toUTFz;
timeInfo.tm_gmtoff = cast(int) convert!("hnsecs", "seconds")(adjTime - _stdTime);
auto zone = (timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName);
auto zone = timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName;
timeInfo.tm_zone = zone.toUTFz!(char*)();
}

Expand Down Expand Up @@ -2408,6 +2423,29 @@ public:
assert(to!string(timeInfo.tm_zone) == "PDT");
}
}

// This is more to verify that SysTime.init.toTM() doesn't segfault and
// does something sane rather than that the value is anything
// particularly useful.
{
auto timeInfo = SysTime.init.toTM();

assert(timeInfo.tm_sec == 0);
assert(timeInfo.tm_min == 0);
assert(timeInfo.tm_hour == 0);
assert(timeInfo.tm_mday == 1);
assert(timeInfo.tm_mon == 0);
assert(timeInfo.tm_year == -1899);
assert(timeInfo.tm_wday == 1);
assert(timeInfo.tm_yday == 0);
assert(timeInfo.tm_isdst == 0);

version(Posix)
{
assert(timeInfo.tm_gmtoff == 0);
assert(to!string(timeInfo.tm_zone) == "SysTime.init's timezone");
}
}
}


Expand Down Expand Up @@ -9069,18 +9107,65 @@ private:
}


// Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5058
/+
invariant()
final class InitTimeZone : TimeZone
{
public:

static immutable(InitTimeZone) opCall() @safe pure nothrow @nogc { return _initTimeZone; }

@property override bool hasDST() @safe const nothrow @nogc { return false; }

override bool dstInEffect(long stdTime) @safe const nothrow @nogc { return false; }

override long utcToTZ(long stdTime) @safe const nothrow @nogc { return 0; }

override long tzToUTC(long adjTime) @safe const nothrow @nogc { return 0; }

override Duration utcOffsetAt(long stdTime) @safe const nothrow @nogc { return Duration.zero; }

private:

this() @safe immutable pure
{
super("SysTime.init's timezone", "SysTime.init's timezone", "SysTime.init's timezone");
}

static immutable InitTimeZone _initTimeZone = new immutable(InitTimeZone);
}

// https://issues.dlang.org/show_bug.cgi?id=17732
@safe unittest
{
assert(SysTime.init.timezone is InitTimeZone());
assert(SysTime.init.toISOString() == "00010101T000000+00:00");
assert(SysTime.init.toISOExtString() == "0001-01-01T00:00:00+00:00");
assert(SysTime.init.toSimpleString() == "0001-Jan-01 00:00:00+00:00");
assert(SysTime.init.toString() == "0001-Jan-01 00:00:00+00:00");
}

// Assigning a value to _timezone in SysTime.init currently doesn't work due
// to https://issues.dlang.org/show_bug.cgi?id=17740. So, to hack around
// that problem, these accessors have been added so that we can insert a
// runtime check for null and then use InitTimeZone for SysTime.init (which
// which is the only case where _timezone would be null). This thus fixes
// the problem with segfaulting when using SysTime.init but at the cost of
// what should be an unnecessary null check. Once 17740 has finally been
// fixed, _timezoneStorage should be removed, these accessors should be
// removed, and the _timezone variable declaration should be restored.
pragma(inline, true) @property _timezone() @safe const pure nothrow @nogc
{
return _timezoneStorage is null ? InitTimeZone() : _timezoneStorage;
}

pragma(inline, true) @property void _timezone(immutable TimeZone tz) @safe pure nothrow @nogc scope
{
assert(_timezone !is null, "Invariant Failure: timezone is null. Were you foolish enough to use " ~
"SysTime.init? (since timezone for SysTime.init can't be set at compile time).");
_timezoneStorage = tz;
}
+/


long _stdTime;
Rebindable!(immutable TimeZone) _timezone;
Rebindable!(immutable TimeZone) _timezoneStorage;
//Rebindable!(immutable TimeZone) _timezone = InitTimeZone();
}

///
Expand Down

0 comments on commit ec8bb20

Please sign in to comment.