Pull to refresh

Comments 44

UFO just landed and posted this here
ок. A наследуется от DynamicObject
UFO just landed and posted this here
согласен, не подходит.
другой вариант без ложек — у нас свой FactAttribute.
UFO just landed and posted this here
Это что то вроде «при желании у меня любой тест заработает» ;)
тест здесь только для краткого формулирования условий задачи. Сама задачи на знания и фантазию
Возможно когда одно поле обычное, а второе имеет статический эквивалент?
что значит статический эквивалент? хочу обратить внимание, что значения полей выставляются рефлексией
В msdn написано, что он и среди статических и среди инстансовых ищет, я думал там можно как-то нахитрить подобным образом, а оказалось что нельзя одинаковые имена делать.
верно, это самое простое и гениальное на мой взгляд решение, если задуматься почему при этом тест проходит.
Но есть и еще решения, без структур
тест пройдет, т.к. изменятся поле копии структуры в куче, а исходная структура в стеке остается неизменной
Поясните пожалуйста для невдупляющих откуда в куче возьмется копия структуры
структуры передаются по значению, поэтому, при вызове SetValue, структура боксится и метод работает уже с сылкой на эту структуру в куче
Тоже про это подумал.
Получилось когда поле с объявлено два раза на русском и англ. =)
))) Вы меняете условие задачи — в тесте все по-английски ;)
        public class X
        {
            public int b;
            public int c;
        }

        public class A : X
        {
            public int b { get; set; }
            public int c { get; set; }
        }

при этом студия честно предупреждает о том, что поля родительского класса скрыты
Объясните, а как это работает?
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Вот такое тоже работает :)

  public class X
  {
    public int b;
    public int c;
  }

  public class A : X
  {
    internal int b;
    internal int c;
  }
Пометить поля a и b в классе A атрибутом
[FieldOffset(0)]
Вообще тема с FieldOffset заслуживает отдельного топика и иследования, но лень с этим возиться. Вот кстати еще один очень интересный пример использования

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication26 {
	class Program {
		static void Main(string[] args) {
			var testString = "habrahabr";
			Console.WriteLine(testString.Length); // out: 9

			var shell = new StringShell();
			shell.str = testString;

			Console.WriteLine(shell.hack/*ссылка на Bytes*/.GetType()); 
			// GetType врет ?)  out: System.String

			// ну и самое интересное, не является ли это уязвимостью?
			shell.hack.b0 = 143;

			Console.WriteLine(testString.Length); // Ахтунт! out: 143 
			
			// А если еще сделать так
			Console.WriteLine(testString); // out: %содержимое кучи%
		}
	}

	// интересная особенность, StructLayout работает для классов
	[StructLayout(LayoutKind.Explicit)]
	public class StringShell {
		[FieldOffset(0)]
		public String str;
		[FieldOffset(0)]
		public Bytes hack;
	}
	// сюда можно добавить столько полей, 
	// на сколько мы хотим пролезть "вглубь" кучи
	// далее расположения "хакнутого" объкта
	public class Bytes {
		public byte b0;
		public byte b1;
 		public byte b2;
		public byte b3;

		public byte b4;
		public byte b5;
		public byte b6;
		public byte b7;
	}
}
Самое интересное, что если компилить C# 3.5, то все работает как положено:

H:\Visual Studio 2005\Projects>test_heap.exe
9
System.String
9
habrahabr

А вот если 4.0 то да, дыра…
Тут не от версии сишарпа зависит, а скорее всего, влияет то, что смещение поля длины строки в 4 и 3.5 дотнете разные. И кстати, код не проходит валидацию peverify.exe
От версии сишарпа зависит целевой рантайм, потому и работает по разному…
Да, дело в смещении, в 3.5 работает с b4 (shell.hack.b4 = 143)

  class A
         {

             public int b, c;
             public A GetType()
             {
                 return this;
             }
             public A GetField(string value)
             {
                return this;
             }
             public void SetValue(A instance, int value)
             { 
                       // Nothing here
             }
        }

Еще есть вариант с using Assert = MyAssert
UFO just landed and posted this here
По порядку появления в голове:
1. Структура
2. [FieldOffset]
3. Поле Assert со своим Equal()
4. Переопределение полей как свойств

В в голове не появились (было выше):
5. Переопределение GetType
6. Тред с перезаписью значений
треда с перезаписью значений вроде нету выше.
У меня была такая идея, но в получившейся реализации тест проходил от случая к случаю
Значит всё же голове появилось, но навела фраза «добавим в тред немного извращений» )
Но всё равно нестабильно будет. Даже при макс. приоритете на тред.
Можно предположить, что A является структурой.
Тогда такое поведение возможно.
Что-то я не понял, в чем сложность…

class A
{
  public int b { get { return 42; } set {} }
  public int c { get { return 42; } set {} }
}
В примере не свойства а поля.
Да, это я ступил. Правильный ответ уже был выше, разве что предупреждения можно убрать:

    class B
    {
        public int b = 42;
        public int c = 42;
    }

    class A : B
    {
        public new int b { get { return 42; } set { } }
        public new int c { get { return 42; } set { } }
    }


Sign up to leave a comment.

Articles