Маршалинг булевской переменной с LayoutKind. Явный, это повреждается или переставший работать, как разработано?

Знайте, что HttpOnly не останавливает сценарии перекрестного сайта; вместо этого, это нейтрализует одно возможное нападение, и в настоящее время делает это только на IE (FireFox представляет cookie HttpOnly в XmlHttpRequest, и Safari не соблюдает его вообще). Любой ценой включите HttpOnly, но не отбрасывайте даже час выходной фильтрации и тестирования пуха в торговле для него.

5
задан Community 23 May 2017 в 12:13
поделиться

3 ответа

Он работает так, как задумано.

Вот что происходит:

Возьмите новый int [] {2, 4} и дайте ему упорядочить его в A, B, Broken, и Broken2. Последний вариант аналогичен Broken, но с обратным порядком полей (сначала b, затем a).

Если мы упорядочим целые числа в эти структуры, мы получим в памяти следующие значения:

  • A: 1, 4
  • B: 2, 1
  • Broken: 2, 1
  • Broken2: 1, 4

Итак, происходит следующее:

  • Когда маршаллер встречает логическое значение, его значение: bool = (original! = 0);
  • Когда есть два поля, которые отображаются в одной и той же памяти, правила последнего поля выигрывают

Итак, для A первое целое число преобразуется в 1, для B - второй int преобразуется в 1, для Broken, поскольку B - последнее поле, применяются его правила, и, следовательно, второе int преобразуется в 1. Аналогично для Broken2.

4
ответ дан 14 December 2019 в 19:17
поделиться

Строка прокомментирована как «FAILS, WOW, WTF?» не выполняется из-за способа выполнения логического сравнения. Он сравнивает 2 с 1:

IL_007e:  ldc.i4.1
IL_007f:  ldloca.s 3
IL_0081:  ldflda valuetype Test/A Test/Broken::a
IL_0086:  ldfld bool Test/A::bValue1
IL_008b:  ceq

ceq в конечном итоге сравнивает 1 с байтом в bValue, который равен 2.

Забавно то, что if (broken.a.bValue1) будет проверять «истина», потому что она не равна нулю.

Что касается другой проблемы (broken.a.iValue2 == 4), она исчезла, когда я применил:

[MarshalAs (UnmanagedType.Bool)]

к обоим логическим полям в структурах. Это гарантирует, что логические значения маршалируются как целое число (4 байта в .NET).

1
ответ дан 14 December 2019 в 19:17
поделиться

Похоже, что EarlNameless верен, поскольку добавление другой структуры int:

    struct C
    {
        public int iValue1;
        public int iValue2;
    }

в конец объединения, кажется, решает, по крайней мере, часть проблемы. Однако это по-прежнему ошибочно, поскольку логическое значение будет рассматривать только однобайтовое значение и, как показано, не является надежным. Наконец, лучший ответ, который я придумал, - использовать настраиваемый тип для маршалинга.

[Serializable]
[ComVisible(true)]
public struct BOOL : IComparable, IConvertible, IComparable<BOOL>, IEquatable<BOOL>, IComparable<bool>, IEquatable<bool>
{
    private uint _data;

    public BOOL(bool value) { _data = value ? 1u : 0u; }
    public BOOL(int value) { _data = unchecked((uint)value); }
    public BOOL(uint value) { _data = value; }

    private bool Value { get { return _data != 0; } }
    private IConvertible Convertible { get { return _data != 0; } }

    #region IComparable Members
    public int CompareTo(object obj) { return Value.CompareTo(obj); }
    #endregion
    #region IConvertible Members
    public TypeCode GetTypeCode() { return Value.GetTypeCode(); }
    public string ToString(IFormatProvider provider) { return Value.ToString(provider); }
    bool IConvertible.ToBoolean(IFormatProvider provider) { return Convertible.ToBoolean(provider); }
    byte IConvertible.ToByte(IFormatProvider provider) { return Convertible.ToByte(provider); }
    char IConvertible.ToChar(IFormatProvider provider) { return Convertible.ToChar(provider); }
    DateTime IConvertible.ToDateTime(IFormatProvider provider) { return Convertible.ToDateTime(provider); }
    decimal IConvertible.ToDecimal(IFormatProvider provider) { return Convertible.ToDecimal(provider); }
    double IConvertible.ToDouble(IFormatProvider provider) { return Convertible.ToDouble(provider); }
    short IConvertible.ToInt16(IFormatProvider provider) { return Convertible.ToInt16(provider); }
    int IConvertible.ToInt32(IFormatProvider provider) { return Convertible.ToInt32(provider); }
    long IConvertible.ToInt64(IFormatProvider provider) { return Convertible.ToInt64(provider); }
    sbyte IConvertible.ToSByte(IFormatProvider provider) { return Convertible.ToSByte(provider); }
    float IConvertible.ToSingle(IFormatProvider provider) { return Convertible.ToSingle(provider); }
    ushort IConvertible.ToUInt16(IFormatProvider provider) { return Convertible.ToUInt16(provider); }
    uint IConvertible.ToUInt32(IFormatProvider provider) { return Convertible.ToUInt32(provider); }
    ulong IConvertible.ToUInt64(IFormatProvider provider) { return Convertible.ToUInt64(provider); }
    object IConvertible.ToType(Type conversionType, IFormatProvider provider) { return Convertible.ToType(conversionType, provider); }
    #endregion
    #region IComparable<bool> Members
    public int CompareTo(BOOL other) { return Value.CompareTo(other.Value); }
    public int CompareTo(bool other) { return Value.CompareTo(other); }
    #endregion
    #region IEquatable<bool> Members
    public bool Equals(BOOL other) { return Value.Equals(other.Value); }
    public bool Equals(bool other) { return Value.Equals(other); }
    #endregion
    #region Object Override
    public override string ToString() { return Value.ToString(); }
    public override int GetHashCode() { return Value.GetHashCode(); }
    public override bool Equals(object obj) { return Value.Equals(obj); }
    #endregion
    #region implicit/explicit cast operators
    public static implicit operator bool(BOOL value) { return value.Value; }
    public static implicit operator BOOL(bool value) { return new BOOL(value); }
    public static explicit operator int(BOOL value) { return unchecked((int)value._data); }
    public static explicit operator BOOL(int value) { return new BOOL(value); }
    public static explicit operator uint(BOOL value) { return value._data; }
    public static explicit operator BOOL(uint value) { return new BOOL(value); }
    #endregion
    #region +, -, !, ~, ++, --, true, false unary operators overloaded.
    public static BOOL operator !(BOOL b) { return new BOOL(!b.Value); }
    public static bool operator true(BOOL b) { return b.Value; }
    public static bool operator false(BOOL b) { return !b.Value; }
    #endregion
    #region +, -, *, /, %, &, |, ^, <<, >> binary operators overloaded.
    public static BOOL operator &(BOOL b1, BOOL b2) { return new BOOL(b1.Value & b2.Value); }
    public static BOOL operator |(BOOL b1, BOOL b2) { return new BOOL(b1.Value | b2.Value); }
    #endregion
    #region ==, !=, <, >, <=, >= comparison operators overloaded
    public static bool operator ==(BOOL b1, BOOL b2) { return (b1.Value == b2.Value); }
    public static bool operator !=(BOOL b1, BOOL b2) { return (b1.Value != b2.Value); }
    #endregion
}
0
ответ дан 14 December 2019 в 19:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: