Skip to content

Type.MakeGenericType and MethodInfo.MakeGenericMethod should be marked dangerous #890

@mthjones

Description

@mthjones

Use of these methods can allow for complete bypass of analyzers. For example, it's possible to make an object that to any outside observer is [Immutable] but has interior mutability with no auditing necessary.

Repro:

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using static D2L.CodeStyle.Annotations.Objects;

namespace ImmutableBypass {
	[Immutable]
	public interface IImmutableInterface {
		ImmutableArray<string> Values { get; }
		void Oops();
	}

	[Immutable]
	public sealed class DefinitelyAnImmutableType<[Immutable] T> : IImmutableInterface
		where T : ICollection<string>, new()
	{
		public T SuperImmutableProperty { get; } = new T();
		public ImmutableArray<string> Values => SuperImmutableProperty.ToImmutableArray();
		
		public void Oops() {
			SuperImmutableProperty.Add( Guid.NewGuid().ToString() );
		}
	}

	public static class Program {
		public static void Main( string[] args ) {
			IImmutableInterface immutableObj = CreateImmutableObject();

			Console.WriteLine( immutableObj.Values.Length ); // => 0

			immutableObj.Oops();

			Console.WriteLine( immutableObj.Values.Length ); // => 1
		}

		private static IImmutableInterface CreateImmutableObject() {
			Type immutableType = typeof( DefinitelyAnImmutableType<> ).MakeGenericType( typeof( List<string> ) );
			return (IImmutableInterface)Activator.CreateInstance( immutableType );
		}
	}
}

(note: checking that constraints are immutable could also help, but also potentially possible to bypass by just doing an is/as cast at runtime)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions