{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/26091","repository_url":"https://api.github.com/repos/dotnet/roslyn","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/26091/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/26091/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/26091/events","html_url":"https://github.com/dotnet/roslyn/issues/26091","id":313133513,"number":26091,"title":"Impossible NullReferenceException","user":{"login":"SergeyTeplyakov","id":726448,"avatar_url":"https://avatars3.githubusercontent.com/u/726448?v=4","gravatar_id":"","url":"https://api.github.com/users/SergeyTeplyakov","html_url":"https://github.com/SergeyTeplyakov","followers_url":"https://api.github.com/users/SergeyTeplyakov/followers","following_url":"https://api.github.com/users/SergeyTeplyakov/following{/other_user}","gists_url":"https://api.github.com/users/SergeyTeplyakov/gists{/gist_id}","starred_url":"https://api.github.com/users/SergeyTeplyakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SergeyTeplyakov/subscriptions","organizations_url":"https://api.github.com/users/SergeyTeplyakov/orgs","repos_url":"https://api.github.com/users/SergeyTeplyakov/repos","events_url":"https://api.github.com/users/SergeyTeplyakov/events{/privacy}","received_events_url":"https://api.github.com/users/SergeyTeplyakov/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-04-11T00:28:51Z","updated_at":"2018-04-11T00:40:54Z","closed_at":null,"author_association":"NONE","body":"**Version Used**: Visual Studio 15.6.2\r\n\r\n**Steps to Reproduce**:\r\nThe following code throws `NullReferenceException` but not `IndexOutOfRangeException`:\r\n\r\n```csharp\r\npublic unsafe struct FixedBytes\r\n{\r\n    public const int MaxLength = 33;\r\n    private fixed byte _bytes[MaxLength];\r\n\r\n    public FixedBytes(BinaryReader reader, int length = MaxLength)\r\n    {\r\n        if (reader == null) throw new ArgumentNullException();\r\n\r\n        var buffer = reader.ReadBytes(length);\r\n\r\n        fixed (byte* p = _bytes, s = buffer)\r\n        {\r\n            for (var i = 0; i < length; i++)\r\n            {\r\n                p[i] = s[i];\r\n            }\r\n        }\r\n    }\r\n}\r\nclass Program\r\n{\r\n    static void Main(string[] args)\r\n    {\r\n        var ms = new MemoryStream(new byte[0]);\r\n        var dr = new BinaryReader(ms);\r\n        FixedBytes fb = new FixedBytes(dr);\r\n    }\r\n}\r\n```\r\n**Expected Behavior**:\r\nThe code should throw `IndexOutOfRangeException`.\r\n\r\n**Actual Behavior**:\r\nThe code throws `NullReferenceException`.\r\n\r\nHere how the decompiled version of this code looks like:\r\n\r\n```csharp\r\npublic unsafe FixedBytes(BinaryReader reader, int length = 33)\r\n{\r\n\tif (reader == null)\r\n\t{\r\n\t\tthrow new ArgumentNullException();\r\n\t}\r\n\tbyte[] arg_1F_0 = reader.ReadBytes(length);\r\n\tfixed (byte** ptr = (byte**)(&this._bytes.FixedElementField))\r\n\t{\r\n\t\tbyte* p = (byte*)ptr;\r\n\t\tfixed (byte[] array = arg_1F_0)\r\n\t\t{\r\n\t\t\tbyte* s;\r\n\t\t\tif (arg_1F_0 == null || array.Length == 0)\r\n\t\t\t{\r\n\t\t\t\ts = null;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ts = &array[0];\r\n\t\t\t}\r\n\t\t\tfor (int i = 0; i < length; i++)\r\n\t\t\t{\r\n\t\t\t\tp[i] = s[i]; // <- This will throw NRE if arg_1F_0 is null or empty\r\n\t\t\t}\r\n\t\t\tptr = null;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n}\r\n```\r\nIt means that if a reader returns an empty array, the `s` local is `null` and NRE is thrown."},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/380290436","html_url":"https://github.com/dotnet/roslyn/issues/26091#issuecomment-380290436","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/26091","id":380290436,"user":{"login":"CyrusNajmabadi","id":4564579,"avatar_url":"https://avatars3.githubusercontent.com/u/4564579?v=4","gravatar_id":"","url":"https://api.github.com/users/CyrusNajmabadi","html_url":"https://github.com/CyrusNajmabadi","followers_url":"https://api.github.com/users/CyrusNajmabadi/followers","following_url":"https://api.github.com/users/CyrusNajmabadi/following{/other_user}","gists_url":"https://api.github.com/users/CyrusNajmabadi/gists{/gist_id}","starred_url":"https://api.github.com/users/CyrusNajmabadi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CyrusNajmabadi/subscriptions","organizations_url":"https://api.github.com/users/CyrusNajmabadi/orgs","repos_url":"https://api.github.com/users/CyrusNajmabadi/repos","events_url":"https://api.github.com/users/CyrusNajmabadi/events{/privacy}","received_events_url":"https://api.github.com/users/CyrusNajmabadi/received_events","type":"User","site_admin":false},"created_at":"2018-04-11T00:40:54Z","updated_at":"2018-04-11T00:40:54Z","author_association":"CONTRIBUTOR","body":"> An expression of an array_type with elements of an unmanaged type T, provided the type T* is implicitly convertible to the pointer type given in the fixed statement. In this case, the initializer computes the address of the first element in the array, and the entire array is guaranteed to remain at a fixed address for the duration of the fixed statement. [b]If the array expression is null or if the array has zero elements, the initializer computes an address equal to zero.[/b]\r\n\r\nhttps://github.com/dotnet/csharplang/blob/master/spec/unsafe-code.md#the-fixed-statement\r\n\r\n"}}
{"actor":{"display_login":"CyrusNajmabadi"}}