## Error in handling of /etc/localtime file to retrieve time zone on Linux

_Submitted by a community member on 2015-05-22 12:04 UTC_

On Linux Mono uses the /etc/localtime file to figure out the time zone.  If appears that if /etc/localtime is an actual file instead of a symbolic link to the file building mono fails with a System.TimeZoneNotFoundException when mdoc is run:

MDOC    [net\_4\_5] cs-errors.tree
mdoc: System.TimeZoneNotFoundException: Exception of type 'System.TimeZoneNotFoundException' was thrown.
```
  at System.TimeZoneInfo.get_Local () <0x100003bd0930 + 0x00134> in <filename unknown>:0 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (DateTime time, System.Boolean& isAmbiguousLocalDst) <0x100003bd0848 + 0x00038> in <filename unknown>:0 
  at System.DateTime.get_Now () <0x100003bcff98 + 0x00084> in <filename unknown>:0 
  at ICSharpCode.SharpZipLib.Zip.ZipEntry..ctor (System.String name, Int32 versionRequiredToExtract, Int32 madeByInfo) <0x100003bcfcd0 + 0x00088> in <filename unknown>:0 
  at ICSharpCode.SharpZipLib.Zip.ZipEntry..ctor (System.String name) <0x100003bcfbb8 + 0x0003c> in <filename unknown>:0 
  at Monodoc.Storage.ZipStorage.SetupEntry (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipOutput, System.String& id) <0x100003bcf9d8 + 0x000fc> in <filename unknown>:0 
  at Monodoc.Storage.ZipStorage.Store (System.String id, System.IO.Stream stream) <0x100003bcc808 + 0x00064> in <filename unknown>:0 
  at Monodoc.Providers.ErrorProvider.CloseTree (Monodoc.HelpSource hs, Monodoc.Tree tree) <0x100003ba7f50 + 0x00278> in <filename unknown>:0 
  at Mono.Documentation.MDocAssembler.Run (IEnumerable`1 args) <0x100002c3b0f8 + 0x014c4> in <filename unknown>:0 
  at Mono.Documentation.MDoc.Run (System.String[] args) <0x100002bd4688 + 0x00d64> in <filename unknown>:0 
  at Mono.Documentation.MDoc.Main (System.String[] args) <0x100002bd3af0 + 0x00084> in <filename unknown>:0 
```

Various test cases also fail with the same exception when doing a make check as well.

If I set the TZ environment variable then everything works OK.  For example this works:

export TZ="/usr/share/zoneinfo/US/Central"

On different Linux varieties /etc/localtime is either an actual file or a symbolic link to a file.  Some varieties require it to be one or the other.  On Ubuntu it is an actual file for instance.  On the Ubuntu system I am using:

seurer@genoa:~/mono-git/mono$ ls -l /etc/localtime
\-rw-r--r-- 1 root root 3559 Apr 27 08:16 /etc/localtime

That is an actual file.  It is a copy of another file from the zoneinfo directory tree:

seurer@genoa:~/mono-git/mono$ ls -l /usr/share/zoneinfo/US/Central
\-rw-r--r-- 1 root root 3559 Apr 26 17:57 /usr/share/zoneinfo/US/Central

If I compare the two they are the same:

seurer@genoa:~/mono-git/mono$ diff --binary /etc/localtime /usr/share/zoneinfo/US/Central
seurer@genoa:~/mono-git/mono$

Note that this is the same file that worked when I set the TZ environment variable.

* * *

_Xamarin Bugzilla comment 1 by a community member on 2015-06-04 19:20 UTC_

It is the same is no /etc/localtime file is present (and no TZ is set) - for the machines that run in the UTC.

* * *

_Xamarin Bugzilla comment 2 by a community member on 2015-06-05 10:29 UTC_

Here is another example when running some compiled code through mono:

seurer@genoa:~/mono-git/mono-ppc64le/mono/tests$ export TZ="/usr/share/zoneinfo/US/Central"
seurer@genoa:~/mono-git/mono-ppc64le/mono/tests$ printenv TZ
/usr/share/zoneinfo/US/Central
seurer@genoa:~/mono-git/mono-ppc64le/mono/tests$ ../mini/mono bug-10127.exe
Starting cache testers
seurer@genoa:~/mono-git/mono-ppc64le/mono/tests$ unset TZ
seurer@genoa:~/mono-git/mono-ppc64le/mono/tests$ ../mini/mono bug-10127.exe
Starting cache testers

Unhandled Exception:
System.TypeInitializationException: The type initializer for 'WeakReferenceTest.Tester' threw an exception. ---\> System.TimeZoneNotFoundException: Exception of type 'System.TimeZoneNotFoundException' was thrown.
```
  at System.TimeZoneInfo.get_Local () <0x3fffad26b738 + 0x00134> in <filename unknown>:0 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (DateTime time, System.Boolean& isAmbiguousLocalDst) <0x3fffad26b650 + 0x00038> in <filename unknown>:0 
  at System.DateTime.get_Now () <0x3fffad26ad40 + 0x00084> in <filename unknown>:0 
  at WeakReferenceTest.Tester..cctor () <0x3fffad26ac50 + 0x00030> in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at WeakReferenceTest.MainClass.Main (System.String[] args) <0x3fffad243ac0 + 0x00128> in <filename unknown>:0 
```

[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The type initializer for 'WeakReferenceTest.Tester' threw an exception. ---\> System.TimeZoneNotFoundException: Exception of type 'System.TimeZoneNotFoundException' was thrown.
```
  at System.TimeZoneInfo.get_Local () <0x3fffad26b738 + 0x00134> in <filename unknown>:0 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (DateTime time, System.Boolean& isAmbiguousLocalDst) <0x3fffad26b650 + 0x00038> in <filename unknown>:0 
  at System.DateTime.get_Now () <0x3fffad26ad40 + 0x00084> in <filename unknown>:0 
  at WeakReferenceTest.Tester..cctor () <0x3fffad26ac50 + 0x00030> in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at WeakReferenceTest.MainClass.Main (System.String[] args) <0x3fffad243ac0 + 0x00128> in <filename unknown>:0
```


* * *

_Xamarin Bugzilla comment 3 by Jo Shields [MSFT] on 2015-06-05 10:29 UTC_

\*\*\* Bug 30839 has been marked as a duplicate of this bug. \*\*\*

* * *

_Xamarin Bugzilla comment 4 by a community member on 2015-06-05 16:21 UTC_

line 123 of mcs/class/corlib/System/TimeZoneInfo.cs

should be changed to "return Utc;" instead of "return null;"

or maybe better:

one could differentiate between InvalidTimeZoneException being thrown from BuildFromStream() and plain TimeZoneNotFoundException from FindSystemTimeZoneByFileName() which should just "return Utc" in line 485 instead of throwing an exception

* * *

_Xamarin Bugzilla comment 5 by a community member on 2015-06-07 17:49 UTC_

I'd like to propose a fix:

<https://github.com/mono/mono/pull/1860>

* * *

_Xamarin Bugzilla comment 6 by Jo Shields [MSFT] on 2015-06-08 03:18 UTC_

(In reply to comment #5)
```
> I'd like to propose a fix:
> 
> https://github.com/mono/mono/pull/1860
```

This is a workaround for the issue at hand (and not necessarily wrong) - but given the issue here only happens on ppc64el, on systems with a valid /etc/localtime, then there are other problems to consider

* * *

_Xamarin Bugzilla comment 7 by a community member on 2015-06-08 03:22 UTC_

Can you test this patch on ppc64? I have had this on x64 FreeBSD, pretty standard setup when no timezone is set.

* * *

_Xamarin Bugzilla comment 8 by a community member on 2015-06-08 04:20 UTC_

I cannot reproduce the original report (using this simple code):

\----------------
using System;
namespace timezoneinforepro1
{
```
    class Program
    {
        static void Main(string[] args)
        {
            DateTime now = DateTime.Now;
            Console.WriteLine("It is now: " + now);
        }
    }
```

}
\----------------

Having <https://github.com/mono/mono/pull/1860> applied and no $TZ set I get the current date and time printed correctly, regardless whether /etc/localtime is a copy of the timezone data or a symbolic link.

* * *

_Xamarin Bugzilla comment 9 by a community member on 2015-08-10 17:16 UTC_

A couple of notes:

The problem is not that the time zone files do not exist.  They do exist.

In ParseTransitions in TimeZoneInfo.cs when this line

```
   var list = new List<KeyValuePair<DateTime, TimeType>> (count);
```

is hit it throws this exception:

System.OverflowException: Arithmetic operation resulted in an overflow.
```
  at (wrapper alloc) System.Object:AllocVector (intptr,intptr)
  at System.Collections.Generic.List`1[T]..ctor (Int32 capacity) <0x3fffb1f78028 + 0x000c4> in <filename unknown>:0 
  at System.TimeZoneInfo.ParseTransitions (System.Byte[] buffer, Int32 index, Int32 count, System.Collections.Generic.Dictionary`2 time_types) <0x3fffb1f77c20 + 0x00104> in <filename unknown>:0 .
```

"count" is 235 here.

When an exception is thrown here it is caught all the way back in CreateLocal().  This occurs whether the TZ env var is set or not.  

But note the difference in what happens when the exception is caught.  When TZ is set the exception causes "Utc" to be returned.  When TZ is not set then null is returned which then causes some code further upstream to throw the System.TimeZoneNotFoundException.

From CreateLocal in TimeZoneInfo.cs:
```
			var tz = Environment.GetEnvironmentVariable ("TZ");
			if (tz != null) {
				if (tz == String.Empty)
					return Utc;
				try {
					return FindSystemTimeZoneByFileName (tz, Path.Combine (TimeZoneDirectory, tz));
				} catch {
					return Utc;
				}
			}
```

```
			try {
				return FindSystemTimeZoneByFileName ("Local", "/etc/localtime");	
			} catch {
				try {
					return FindSystemTimeZoneByFileName ("Local", Path.Combine (TimeZoneDirectory, "localtime"));	
				} catch {
					return null;
				}
			}
```


* * *

_Xamarin Bugzilla comment 10 by a community member on 2015-08-10 17:25 UTC_

So the latter problem (catching the exception) has been fixed in

<https://github.com/mono/mono/pull/1860>

(now in Mono git master) - see the discussion related to this bug in <https://github.com/saper/mono/commit/cf4e7339e31d19e6934d7b8130f82697212ea39e>

The exception should be propagated correctly.

No idea about the collections bug though. Can you publish your timezone files somewhere so that someone may try to reproduce it?

* * *

_Xamarin Bugzilla comment 11 by a community member on 2015-08-10 17:30 UTC_

As an experiment I changed that line in ParseTransitions to not provide an initial element count for the call to "new List".  Without the count the code properly reads the timezone file and works just fine.

So I'd say there is some issue in the List constructor.

The timezone files do not appear to have anything to do with it but are the standard ones that come with Ubuntu 14.04.

* * *

_Xamarin Bugzilla comment 12 by a community member on 2015-08-10 17:37 UTC_

Just wondering, can you reproduce it with a minimal C# test case? It might be worth filling a dedicated bug.

Is this running on PPC64? Do you see this issue on any other platform?

(re files: sorry no Ubuntu here, running FreeBSD :)

* * *

_Xamarin Bugzilla comment 13 by a community member on 2015-08-10 19:07 UTC_


The following will reproduce it.  I am on a power LE system but will try on a power BE system and see what happens.

using System;

public class Test
{

```
	public static int Main (String[] args) {
		TimeZoneInfo tzinfo = TimeZoneInfo.Local;
		return 0;
	}
```

}

* * *

_Xamarin Bugzilla comment 14 by a community member on 2015-08-10 19:12 UTC_

Any chance to reproduce it with 

```
   var list = new List<KeyValuePair<DateTime, TimeType>> (count);
```

instead? 

Not sure how large those DateTime and TimeType should be to reproduce though.

* * *

_Xamarin Bugzilla comment 15 by a community member on 2015-08-11 10:56 UTC_

I tried the following but that worked (though I had to copy TimeType locally).  I will look into List to see where the exception is coming from.

```
	public static int Main (String[] args) {
		int count=235;
		var list = new List<KeyValuePair<DateTime, TimeType>> (count);
```

//		TimeZoneInfo tzinfo = TimeZoneInfo.Local;
```
		return 0;
	}
```


* * *

_Xamarin Bugzilla comment 16 by a community member on 2015-08-11 11:00 UTC_

Another additional idea: can you run it under gdb and dump a disassembly of around the place where it crashes? Long time I have read PowerPC code but maybe some JIT developers could jump in.

* * *

_Xamarin Bugzilla comment 17 by a community member on 2015-08-12 10:47 UTC_

What appears to be happening is that the code generated by create\_allocator from sgen-mono.c is signaling the overflow exception.  If you look around line 1145 (in my copy) there's some code with this comment:

```
		/*
		 * n > MONO_ARRAY_MAX_INDEX => OutOfMemoryException
		 * n < 0                    => OverflowException
		 *
		 * We can do an unsigned comparison to catch both cases, then in the error
		 * case compare signed to distinguish between them.
		 */
```

A little ways down you an see where it checks for the overflow.  I am going to try to catch this in the debugger in the actual generated code to see if I can figure out what is going haywire here.

* * *

_Xamarin Bugzilla comment 18 by a community member on 2015-08-12 12:41 UTC_

When it gets into the actual allocation code one of the parms has been corrupted.

(gdb) print mono\_pmip($pc)
$16 = 0x1089c650 " (wrapper alloc) object:AllocVector (intptr,intptr) + 0x0 (0x3fffb5645270 0x3fffb56454c8) [0x10563e50 - hello.exe]"

(gdb) print/x $r4
$20 = 0xffeb0000000000eb

Register 4 should have 235 in it which is the number of elements being allocated.  0xeb is 235 but something either overwrote part of or more likely didn't properly save/restore the register along the way.  0xffeb0000000000eb has the sign bit set and so looks negative to the code that I mentioned above.  I stepped all the way through the call sequence so I should be able to find the problem spot.

* * *

_Xamarin Bugzilla comment 19 by a community member on 2015-08-12 17:13 UTC_

The problem is not in the count parameter but in how AllocVector treats it.  The parameter is an int (32 bits) and so word instructions are used to manipulate it up to the point where it is in AllocVector.  AllocVector generates doubleword (64 bit) instructions while using word operands without converting them to doublewords first.

I changed the code in List.cs to convert the integer (32 bit) capacity parameter it uses to a long (64 bit) before it allocates the array.  Then AllocVector works OK and the timezone problem vanishes.  This is just a workaround to the actual problem in AllocVector of course.

This probably causes problems elsewhere but here the leftover bits in the upper (unused) part of the parameter register just happened to trigger the exception and so it was caught.

* * *

_Xamarin Bugzilla comment 20 by a community member on 2015-08-13 14:43 UTC_

Working on this some more I found the ultimate problem.

When the timezone information is read from the file in TimeZoneInfo.cs it is mishandling a big-endian little-endian int32 on a 64-bit platform conversion.

In this case ParseTZBuffer is trying to read an int32 from the file (actually, a buffer read from the file).  At offset 32 the buffer contains 0xeb000000, i.e., 235.

int timecnt = ReadBigEndianInt32 (buffer, 32);

ReadBigEndianInt32 calls BitConverter.ToInt32 which reads the value into a register as 0xffffffffeb000000 because it generates a load with sign extension on the buffer containing 0xeb000000.

Then because this is little endian it calls SwapInt32.

```
		static int SwapInt32 (int i)
		{
			return (((i >> 24) & 0xff)
				| ((i >> 8) & 0xff00)
				| ((i << 8) & 0xff0000)
				| ((i << 24)));
		}
```

The "i\<\<24" is the problem spot which produces "0xffeb000000000000" in this case.  When put together with the rest it comes out as 0xffeb0000000000eb.  That value if it was stored would actually be OK (a store word will ignore the upper 4 bytes) but if it stays in registers it causes problems.  Mono manages to keep this value in registers the whole time it is being used.

I believe that changing SwapInt32 to the following will fix that:

```
		static int SwapInt32 (int i)
		{
			return (((i >> 24) & 0xff)
				| ((i >> 8) & 0xff00)
				| ((i << 8) & 0xff0000)
				| (((i & 0xff) << 24)));
		}
```


* * *

_Xamarin Bugzilla comment 21 by a community member on 2015-08-13 15:23 UTC_

Bill,

reads like a good book.

I wonder if this is a problem also on other big-endian platforms!

* * *

_Xamarin Bugzilla comment 22 by a community member on 2015-08-13 15:37 UTC_

Heh.  I like to put some details in so that if anyone else is looking at something similar they can get a head start in figuring out what is wrong.

As for other architectures it depends on what instruction(s) they generate for this line in bitconverter.cs

```
                    return *((int *) pbyte);
```

Power generates a load-with-sign-extension (actually an "lwa") and anything similar would probably have similar problems all else being equal.

* * *

_Xamarin Bugzilla comment 23 by a community member on 2015-08-13 16:05 UTC_

What happens if you change "int" to "uint" and BitConverter.Int32 (and maybe Int16 as well) to UInt32?

No wonder it's told to use lwa instead of lwz

* * *

_Xamarin Bugzilla comment 24 by a community member on 2015-08-13 17:38 UTC_

The timezone file description says:

"Six four-byte values of type long, written in a "standard" byte
order (the high-order byte of the value is written first)."

The values are all counts of one sort of another but given the type in theory they could be negative.

* * *

_Xamarin Bugzilla comment 25 by a community member on 2015-08-13 17:51 UTC_

I think that number of items is unsigned. Maybe SwapUInt32 (the "new" one) should have an additional & 0xFFFFFFFF in the end?

* * *

_Xamarin Bugzilla comment 26 by a community member on 2015-08-13 17:54 UTC_

And yet, SwapInt32 (signed) is too simplistic - shouldn't it try harder to preserve the sign?

* * *

_Xamarin Bugzilla comment 27 by a community member on 2015-08-13 19:45 UTC_

....scratch the last one... from the quick look around nobody is doing "signed" byte order transfomation - it makes no sense.... what should be done is probably always to have uint transformation and then cast signed values to int where necessary.

* * *

_Xamarin Bugzilla comment 28 by a community member on 2015-08-14 10:34 UTC_

Yeah, that code is messed up and does not actually handle signed numbers properly.

I may just fix it for now so it works and add a FIXME to clean it up properly later.

* * *

_Xamarin Bugzilla comment 29 by a community member on 2015-08-16 15:40 UTC_

Bill,

I have converted most of the values to unsigned ints.

From my reading of the tzfile(5) manpage[1] it seems
that only the timezone offset is signed long to indicate
west/east GMT offsets.

This one gets an explicit conversion.

Does this:

```
    https://github.com/mono/mono/pull/1982
```

fix the issue for you?

[1] <http://www.freebsd.org/cgi/man.cgi?query=tzfile&apropos=0&sektion=5&manpath=FreeBSD+10.2-RELEASE&arch=default&format=html>

* * *

_Xamarin Bugzilla comment 30 by a community member on 2015-09-03 16:09 UTC_

Marcin, did you ever get your changes to use unsigned ints to fully work?  This is still failing for me with code I just checked out.

* * *

_Xamarin Bugzilla comment 31 by a community member on 2015-09-03 16:29 UTC_

There is something strange about <https://bugzilla.xamarin.com/show_bug.cgi?id=33471> 

Original (unchanged) code fails tests on my FreeBSD system for few reasons,
one is some tests assuming UTC cannot be "local" time :) <https://github.com/mono/mono/pull/1982>

but most importantly attempts to read timezone files fail with:

14) MonoTests.System.TimeZoneInfoTest+FindSystemTimeZoneByIdTests.BrusselsSupportsDST : System.InvalidTimeZoneException : Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
at System.TimeZoneInfo.BuildFromStream (System.String id, System.IO.Stream stream) [0x0003f] in /home/saper/sw/mono/mcs/class/corlib/System/TimeZoneInfo.cs:1153
at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String filepath) [0x00018] in /home/saper/sw/mono/mcs/class/corlib/System/TimeZoneInfo.cs:488
at System.TimeZoneInfo.FindSystemTimeZoneByIdCore (System.String id) [0x0000c] in /home/saper/sw/mono/mcs/class/corlib/System/TimeZoneInfo.cs:132
at System.TimeZoneInfo.FindSystemTimeZoneById (System.String id) [0x00069] in /home/saper/sw/mono/mcs/class/corlib/System/TimeZoneInfo.cs:478
at MonoTests.System.TimeZoneInfoTest+FindSystemTimeZoneByIdTests.BrusselsSupportsDST () [0x0001a] in /home/saper/sw/mono/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs:755
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00038] in /home/saper/sw/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:295

which indicates something is wrong with converting integers on my amd64 FreeBSD system as it stands now.

After my patch those errors are gone, but I start getting:

System.InvalidTimeZoneException: adjustment rules specified in adjustmentRules parameter are not in chronological order

Assuming zdump is doing it in order stored:

Europe/Brussels  Sun Jan  0 00:00:00 1900 UTC = Sun Jan  0 00:00:00 1900 LMT isdst=0 gmtoff=0
Europe/Brussels  Sun Jan  0 00:00:00 1900 UTC = Sun Jan  0 00:00:00 1900 LMT isdst=0 gmtoff=0
Europe/Brussels  Wed Dec 31 23:42:29 1879 UTC = Wed Dec 31 23:59:59 1879 LMT isdst=0 gmtoff=1050
Europe/Brussels  Wed Dec 31 23:42:30 1879 UTC = Thu Jan  1 00:00:00 1880 BMT isdst=0 gmtoff=1050
Europe/Brussels  Sun May  1 11:42:29 1892 UTC = Sun May  1 11:59:59 1892 BMT isdst=0 gmtoff=1050
Europe/Brussels  Sun May  1 11:42:30 1892 UTC = Sun May  1 11:42:30 1892 WET isdst=0 gmtoff=0
Europe/Brussels  Sat Nov  7 23:59:59 1914 UTC = Sat Nov  7 23:59:59 1914 WET isdst=0 gmtoff=0
Europe/Brussels  Sun Nov  8 00:00:00 1914 UTC = Sun Nov  8 01:00:00 1914 CET isdst=0 gmtoff=3600

... then indeed adjustmentRules are not sorted in the file and the assumption in the code is wrong.

* * *

_Xamarin Bugzilla comment 32 by a community member on 2015-09-03 16:43 UTC_

Bill, 

What failures are you seeing after applying the patch?

* * *

_Xamarin Bugzilla comment 33 by a community member on 2015-09-04 10:11 UTC_

I initially didn't try it after I saw you were having problems.  I have been checking in some other fixes and just noticed that the timezone problem was still there so I wondered if you were still working on your fix.

I just tried with your change and there were 30-some test case failures.  I ran one by hand and it got:

Unhandled Exception:
System.InvalidTimeZoneException: Arithmetic operation resulted in an overflow.
```
  at System.TimeZoneInfo.BuildFromStream (System.String id, System.IO.Stream stream) <0x3fffb57dc1f0 + 0x00140> in <filename unknown>:0 
  at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String filepath) <0x3fffb57d7b78 + 0x00090> in <filename unknown>:0 
  at System.TimeZoneInfo.CreateLocal () <0x3fffb57b67a8 + 0x004b8> in <filename unknown>:0 
  at System.TimeZoneInfo.get_Local () <0x3fffb57b6630 + 0x00040> in <filename unknown>:0 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (DateTime time, System.Boolean& isAmbiguousLocalDst) <0x3fffb57b6548 + 0x00038> in <filename unknown>:0 
  at System.DateTime.get_Now () <0x3fffb57b56f8 + 0x00084> in <filename unknown>
```

...etc...

* * *

_Xamarin Bugzilla comment 34 by a community member on 2015-09-04 10:17 UTC_

Would be great to have a mono --debug output with a full stacktrace (with filenames and line numbers)...

* * *

_Xamarin Bugzilla comment 35 by a community member on 2015-09-04 10:43 UTC_

The full trace is this.  It doesn't help all that much because an earlier exception is being caught and re-rethrown:

seurer@genoa:~/mono-git/mono-checkin/mono/tests$ MONO\_PATH="/home/seurer/mono-git/mono-checkin/mcs/class/lib/net\_4\_x" MONO\_CFG\_DIR=/home/seurer/mono-git/mono-checkin/runtime/etc /home/seurer/mono-git/mono-checkin/mono/mini/mono --debug --config /home/seurer/mono-git/mono-checkin/runtime/etc/mono/config loader.exe

Unhandled Exception:
System.InvalidTimeZoneException: Arithmetic operation resulted in an overflow.
```
  at System.TimeZoneInfo.BuildFromStream (System.String id, System.IO.Stream stream) [0x0003f] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:1213 
  at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String filepath) [0x00018] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:548 
  at System.TimeZoneInfo.CreateLocal () [0x000ed] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:179 
  at System.TimeZoneInfo.get_Local () [0x0000c] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:76 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (DateTime time, System.Boolean& isAmbiguousLocalDst) [0x00000] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:487 
  at System.DateTime.get_Now () [0x00008] in /home/seurer/mono-git/mono-checkin/external/referencesource/mscorlib/system/datetime.cs:950 
  at TestDriver.RunTests (System.Type type, System.String[] args) [0x00011] in /home/seurer/mono-git/mono-checkin/mono/mini/TestDriver.cs:29 
  at Tests.Main (System.String[] args) [0x0000c] in /home/seurer/mono-git/mono-checkin/mono/tests/loader.cs:15 
```

[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidTimeZoneException: Arithmetic operation resulted in an overflow.
```
  at System.TimeZoneInfo.BuildFromStream (System.String id, System.IO.Stream stream) [0x0003f] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:1213 
  at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String filepath) [0x00018] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:548 
  at System.TimeZoneInfo.CreateLocal () [0x000ed] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:179 
  at System.TimeZoneInfo.get_Local () [0x0000c] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:76 
  at System.TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc (DateTime time, System.Boolean& isAmbiguousLocalDst) [0x00000] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:487 
  at System.DateTime.get_Now () [0x00008] in /home/seurer/mono-git/mono-checkin/external/referencesource/mscorlib/system/datetime.cs:950 
  at TestDriver.RunTests (System.Type type, System.String[] args) [0x00011] in /home/seurer/mono-git/mono-checkin/mono/mini/TestDriver.cs:29 
  at Tests.Main (System.String[] args) [0x0000c] in /home/seurer/mono-git/mono-checkin/mono/tests/loader.cs:15
```


* * *

_Xamarin Bugzilla comment 36 by a community member on 2015-09-04 11:11 UTC_

I commented out the rethrow and the error is coming from here:

```
		static List<KeyValuePair<DateTime, TimeType>> ParseTransitions (byte [] buffer, uint index, uint count, Dictionary<uint, TimeType> time_types)
		{
			var list = new List<KeyValuePair<DateTime, TimeType>> ((int)count);   // Line 1409
```


<br />

which is called from here 

```
		private static TimeZoneInfo ParseTZBuffer (string id, byte [] buffer, int length)
		{
```

. . .
```
			uint timecnt = ReadBigEndianUInt32 (buffer, 32);
```

. . .
```
			List<KeyValuePair<DateTime, TimeType>> transitions = ParseTransitions (buffer, 44, timecnt, time_types);  // Line 1270
```

timecnt is (as expected) 235.

[ERROR] FATAL UNHANDLED EXCEPTION: System.OverflowException: Arithmetic operation resulted in an overflow.
```
  at (wrapper alloc) System.Object:AllocVector (intptr,intptr)
  at System.Collections.Generic.List`1[T]..ctor (Int32 capacity) [0x0001b] in /home/seurer/mono-git/mono-checkin/external/referencesource/mscorlib/system/collections/generic/list.cs:71 
  at System.TimeZoneInfo.ParseTransitions (System.Byte[] buffer, UInt32 index, UInt32 count, System.Collections.Generic.Dictionary`2 time_types) [0x00000] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:1409 
  at System.TimeZoneInfo.ParseTZBuffer (System.String id, System.Byte[] buffer, Int32 length) [0x00087] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:1270 
  at System.TimeZoneInfo.BuildFromStream (System.String id, System.IO.Stream stream) [0x00030] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:1211 
  at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String filepath) [0x00018] in /home/seurer/mono-git/mono-checkin/mcs/class/corlib/System/TimeZoneInfo.cs:548 
```

...etc...

* * *

_Xamarin Bugzilla comment 37 by a community member on 2015-09-04 11:24 UTC_

I looked through the generated code and this unit code has the same problem with registers that the int code did.  When mono manages to keep everything in registers the shift code:

```
		static uint SwapUInt32 (uint i)
		{
			return (((i >> 24) & 0xff)
				| ((i >> 8) & 0xff00)
				| ((i << 8) & 0xff0000)
				| ((i << 24)));
		}
```


<br />

once again ends up with some stuff in the upper parts of the 64 bit register.  This may be a problem in code gen (perhaps a missing mask operation somewhere?) but can easily be solved by changes the last left shift to:

```
				| (((i & 0xff) << 24)));
```

Hmmm.  Looking at what ToUint32 does in bitconverter.cs it just does this:

```
            return (uint)ToInt32(value, startIndex);
```

I am not sure about C# but in C code that is problematic in this sort of situation.  The cast probably doesn't actually generate any code and thus using ToUInt32 has exactly the same issue that ToInt32 does.

* * *

_Xamarin Bugzilla comment 38 by a community member on 2015-09-24 10:18 UTC_

I pushed a change and created a pull request to fix the problem in SwapInt32.

<https://github.com/mono/mono/pull/2045>

That will take care of the immediate issue but I think that changing everything to unsigned (where appropriate) is better.

* * *

_Xamarin Bugzilla comment 39 by a community member on 2015-10-29 14:42 UTC_

One question Bill, what does BitConverter.IsLittleEndian return for your platform?

* * *

_Xamarin Bugzilla comment 40 by a community member on 2015-10-29 15:08 UTC_

I tried the little test program here:

<https://msdn.microsoft.com/en-us/library/system.bitconverter.islittleendian%28v=vs.110%29.aspx>

And it reported:

IsLittleEndian:  True

* * *

<br />

_Reference: <https://bugzilla.xamarin.com/show_bug.cgi?id=30360>_