Преглед изворни кода

Fix heap corruption for always-boxed generic types in Safety.vala

In Vala generics, int64, uint64, float and double are ALWAYS boxed (heap
pointers) regardless of nullability, and valac rejects their non-nullable
forms as generic type arguments outright. Safety.vala's
safely_read_array/safely_assign_to_array/safely_move_items_in_array and
the get_safe_read_function_for/get_safe_write_function_for dispatchers
nevertheless cast the generic T[] to (int64[])/(uint64[]) etc., treating
elements as unboxed 8-byte values. Reads reinterpreted pointer bits and
copy/ownership semantics were wrong, so teardown aborted with
"free(): invalid size"/"double free or corruption" (glibc).

Remove the int64/uint64/float/double branches from all five dispatchers
and delete the eight now-unreachable unboxed helper functions
(safely_read_/safely_assign_ int64/uint64/float/double). Those types now
fall through to the default pointer path, exactly like reference types.
The remaining typed casts (bool, char, uchar, int, uint, long, ulong,
enums, flags) are for types that are genuinely unboxed in generics.

Grepped src/lib for other typed-array casts of the same flaw - none
found outside Safety.vala.

Re-enabled 9 previously BROKEN-disabled value-type matrix cases that
this fix makes pass (vector/buffer/ring_buffer for int64?/uint64?/
float?; the double? variants were already enabled and still pass).

Verification: full suite 696/696 ok, exit 0; standalone probes for
Vector/Buffer/RingBuffer over int64?/uint64?/float?/double? roundtrip,
insert/remove/clear/resize cycles and 50 repeated runs with no heap
errors.

Note for reviewers: the meson-built test-suite binary resolves
libinvercargill via RUNPATH $ORIGIN/../lib, which the environment's
LD_LIBRARY_PATH=/home/bbarrow/.local/lib64 overrides with a stale
pre-installed copy - run the suite with LD_LIBRARY_PATH=<builddir>/lib
to exercise the freshly built library.
saddle-fedora пре 1 месец
родитељ
комит
b4058de01f
2 измењених фајлова са 129 додато и 231 уклоњено
  1. 0 84
      src/lib/Safety.vala
  2. 129 147
      src/tests/Integration/ValueTypeMatrix.vala

+ 0 - 84
src/lib/Safety.vala

@@ -21,24 +21,12 @@ namespace Invercargill {
         else if (t == typeof (uint)) {
             return ((uint[])array)[index];
         }
-        else if (t == typeof (int64)) {
-            return ((int64[])array)[index];
-        }
-        else if (t == typeof (uint64)) {
-            return ((uint64[])array)[index];
-        }
         else if (t == typeof (long)) {
             return ((long[])array)[index];
         }
         else if (t == typeof (ulong)) {
             return ((ulong[])array)[index];
         }
-        else if (t == typeof (float)) {
-            return ((float?[])array)[index];
-        }
-        else if (t == typeof (double)) {
-            return ((double?[])array)[index];
-        }
         else {
             return array[index];
         }
@@ -61,24 +49,12 @@ namespace Invercargill {
         else if (t == typeof (uint)) {
             ((uint[])array)[index] = (uint)value;
         }
-        else if (t == typeof (int64)) {
-            ((int64[])array)[index] = (int64)value;
-        }
-        else if (t == typeof (uint64)) {
-            ((uint64[])array)[index] = (uint64)value;
-        }
         else if (t == typeof (long)) {
             ((long[])array)[index] = (long)value;
         }
         else if (t == typeof (ulong)) {
             ((ulong[])array)[index] = (ulong)value;
         }
-        else if (t == typeof (float)) {
-            ((float?[])array)[index] = (float?)value;
-        }
-        else if (t == typeof (double)) {
-            ((double?[])array)[index] = (double?)value;
-        }
         else {
             array[index] = value;
         }
@@ -101,24 +77,12 @@ namespace Invercargill {
         else if (t == typeof (uint)) {
             ((uint[])array).move((int)source, (int)destination, (int)count);
         }
-        else if (t == typeof (int64)) {
-            ((int64[])array).move((int)source, (int)destination, (int)count);
-        }
-        else if (t == typeof (uint64)) {
-            ((uint64[])array).move((int)source, (int)destination, (int)count);
-        }
         else if (t == typeof (long)) {
             ((long[])array).move((int)source, (int)destination, (int)count);
         }
         else if (t == typeof (ulong)) {
             ((ulong[])array).move((int)source, (int)destination, (int)count);
         }
-        else if (t == typeof (float)) {
-            ((float?[])array).move((int)source, (int)destination, (int)count);
-        }
-        else if (t == typeof (double)) {
-            ((double?[])array).move((int)source, (int)destination, (int)count);
-        }
         else {
             array.move((int)source, (int)destination, (int)count);
         }
@@ -140,24 +104,12 @@ namespace Invercargill {
     internal uint safely_read_uint_from_array(uint[] array, uint index) {
         return ((uint[])array)[index];
     }
-    internal int64 safely_read_int64_from_array(int64[] array, uint index) {
-        return ((int64[])array)[index];
-    }
-    internal uint64 safely_read_uint64_from_array(uint64[] array, uint index) {
-        return ((uint64[])array)[index];
-    }
     internal long safely_read_long_from_array(long[] array, uint index) {
         return ((long[])array)[index];
     }
     internal ulong safely_read_ulong_from_array(ulong[] array, uint index) {
         return ((ulong[])array)[index];
     }
-    internal float safely_read_float_from_array(float?[] array, uint index) {
-        return ((float?[])array)[index];
-    }
-    internal double? safely_read_double_from_array(double?[] array, uint index) {
-        return ((double?[])array)[index];
-    }
 
     internal void safely_assign_bool_to_array(bool[] array, uint index, bool value) {
         ((bool[])array)[index] = (bool)value;
@@ -174,24 +126,12 @@ namespace Invercargill {
     internal void safely_assign_uint_to_array(uint[] array, uint index, uint value) {
         ((uint[])array)[index] = (uint)value;
     }
-    internal void safely_assign_int64_to_array(int64[] array, uint index, int64 value) {
-        ((int64[])array)[index] = (int64)value;
-    }
-    internal void safely_assign_uint64_to_array(uint64[] array, uint index, uint64 value) {
-        ((uint64[])array)[index] = (uint64)value;
-    }
     internal void safely_assign_long_to_array(long[] array, uint index, long value) {
         ((long[])array)[index] = (long)value;
     }
     internal void safely_assign_ulong_to_array(ulong[] array, uint index, ulong value) {
         ((ulong[])array)[index] = (ulong)value;
     }
-    internal void safely_assign_float_to_array(float?[] array, uint index, float? value) {
-        ((float?[])array)[index] = (float?)value;
-    }
-    internal void safely_assign_double_to_array(double?[] array, uint index, double? value) {
-        ((double?[])array)[index] = (double?)value;
-    }
 
     internal SafeReadFunc<T>? get_safe_read_function_for<T>() {
         var t = typeof (T);
@@ -210,24 +150,12 @@ namespace Invercargill {
         else if (t == typeof (uint)) {
             return (SafeReadFunc<T>)safely_read_uint_from_array;
         }
-        else if (t == typeof (int64)) {
-            return (SafeReadFunc<T>)safely_read_int64_from_array;
-        }
-        else if (t == typeof (uint64)) {
-            return (SafeReadFunc<T>)safely_read_uint64_from_array;
-        }
         else if (t == typeof (long)) {
             return (SafeReadFunc<T>)safely_read_long_from_array;
         }
         else if (t == typeof (ulong)) {
             return (SafeReadFunc<T>)safely_read_ulong_from_array;
         }
-        else if (t == typeof (float)) {
-            return (SafeReadFunc<T>)safely_read_float_from_array;
-        }
-        else if (t == typeof (double)) {
-            return (SafeReadFunc<T>)safely_read_double_from_array;
-        }
         return null;
     }
 
@@ -248,24 +176,12 @@ namespace Invercargill {
         else if (t == typeof (uint)) {
             return (SafeWriteFunc<T>)safely_assign_uint_to_array;
         }
-        else if (t == typeof (int64)) {
-            return (SafeWriteFunc<T>)safely_assign_int64_to_array;
-        }
-        else if (t == typeof (uint64)) {
-            return (SafeWriteFunc<T>)safely_assign_uint64_to_array;
-        }
         else if (t == typeof (long)) {
             return (SafeWriteFunc<T>)safely_assign_long_to_array;
         }
         else if (t == typeof (ulong)) {
             return (SafeWriteFunc<T>)safely_assign_ulong_to_array;
         }
-        else if (t == typeof (float)) {
-            return (SafeWriteFunc<T>)safely_assign_float_to_array;
-        }
-        else if (t == typeof (double)) {
-            return (SafeWriteFunc<T>)safely_assign_double_to_array;
-        }
         return null;
     }
 

+ 129 - 147
src/tests/Integration/ValueTypeMatrix.vala

@@ -997,55 +997,49 @@ void value_type_matrix_ulong_tests() {
 }
 
 void value_type_matrix_int64_tests() {
-    // BROKEN(/invercargill/value_type_matrix/int64/vector): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/int64/vector", () => {
-//         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
-// 
-//         var v = new Vector<int64?>();
-//         foreach (int64? i in items) v.add(i);
-//         assert(v.count() == 4);
-//         assert(v.length == 4);
-//         for (int i = 0; i < 4; i++) {
-//             int64? got;
-//             assert(v.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//         assert(v.to_array().length == 4);
-//         assert(v.to_vector().count() == 4);
-//         assert(v.first_or_default() == items[0]);
-//         assert(v.last_or_default() == items[3]);
-//     });
-
-    // BROKEN(/invercargill/value_type_matrix/int64/buffer): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/int64/buffer", () => {
-//         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
-// 
-//         var b = new Buffer<int64?>(4);
-//         for (int i = 0; i < 4; i++) b.set((uint)i, items[i]);
-//         assert(b.count() == 4);
-//         for (int i = 0; i < 4; i++) {
-//             int64? got;
-//             assert(b.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//     });
-
-    // BROKEN(/invercargill/value_type_matrix/int64/ring_buffer): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/int64/ring_buffer", () => {
-//         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
-// 
-//         var r = new RingBuffer<int64?>(4);
-//         for (int i = 0; i < 4; i++) r.set((uint)i, items[i]);
-//         assert(r.count() == 4);
-//         for (int i = 0; i < 4; i++) {
-//             int64? got;
-//             assert(r.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//     });
+     Test.add_func("/invercargill/value_type_matrix/int64/vector", () => {
+         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
+ 
+         var v = new Vector<int64?>();
+         foreach (int64? i in items) v.add(i);
+         assert(v.count() == 4);
+         assert(v.length == 4);
+         for (int i = 0; i < 4; i++) {
+             int64? got;
+             assert(v.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+         assert(v.to_array().length == 4);
+         assert(v.to_vector().count() == 4);
+         assert(v.first_or_default() == items[0]);
+         assert(v.last_or_default() == items[3]);
+    });
+
+     Test.add_func("/invercargill/value_type_matrix/int64/buffer", () => {
+         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
+ 
+         var b = new Buffer<int64?>(4);
+         for (int i = 0; i < 4; i++) b.set((uint)i, items[i]);
+         assert(b.count() == 4);
+         for (int i = 0; i < 4; i++) {
+             int64? got;
+             assert(b.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+    });
+
+     Test.add_func("/invercargill/value_type_matrix/int64/ring_buffer", () => {
+         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
+ 
+         var r = new RingBuffer<int64?>(4);
+         for (int i = 0; i < 4; i++) r.set((uint)i, items[i]);
+         assert(r.count() == 4);
+         for (int i = 0; i < 4; i++) {
+             int64? got;
+             assert(r.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+    });
 
     Test.add_func("/invercargill/value_type_matrix/int64/series", () => {
         int64?[] items = {5000000000L, -5000000000L, 9223372036854775807L, 0L};
@@ -1204,55 +1198,49 @@ void value_type_matrix_int64_tests() {
 }
 
 void value_type_matrix_uint64_tests() {
-    // BROKEN(/invercargill/value_type_matrix/uint64/vector): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/uint64/vector", () => {
-//         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
-// 
-//         var v = new Vector<uint64?>();
-//         foreach (uint64? i in items) v.add(i);
-//         assert(v.count() == 4);
-//         assert(v.length == 4);
-//         for (int i = 0; i < 4; i++) {
-//             uint64? got;
-//             assert(v.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//         assert(v.to_array().length == 4);
-//         assert(v.to_vector().count() == 4);
-//         assert(v.first_or_default() == items[0]);
-//         assert(v.last_or_default() == items[3]);
-//     });
-
-    // BROKEN(/invercargill/value_type_matrix/uint64/buffer): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/uint64/buffer", () => {
-//         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
-// 
-//         var b = new Buffer<uint64?>(4);
-//         for (int i = 0; i < 4; i++) b.set((uint)i, items[i]);
-//         assert(b.count() == 4);
-//         for (int i = 0; i < 4; i++) {
-//             uint64? got;
-//             assert(b.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//     });
-
-    // BROKEN(/invercargill/value_type_matrix/uint64/ring_buffer): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/uint64/ring_buffer", () => {
-//         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
-// 
-//         var r = new RingBuffer<uint64?>(4);
-//         for (int i = 0; i < 4; i++) r.set((uint)i, items[i]);
-//         assert(r.count() == 4);
-//         for (int i = 0; i < 4; i++) {
-//             uint64? got;
-//             assert(r.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//     });
+     Test.add_func("/invercargill/value_type_matrix/uint64/vector", () => {
+         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
+ 
+         var v = new Vector<uint64?>();
+         foreach (uint64? i in items) v.add(i);
+         assert(v.count() == 4);
+         assert(v.length == 4);
+         for (int i = 0; i < 4; i++) {
+             uint64? got;
+             assert(v.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+         assert(v.to_array().length == 4);
+         assert(v.to_vector().count() == 4);
+         assert(v.first_or_default() == items[0]);
+         assert(v.last_or_default() == items[3]);
+    });
+
+     Test.add_func("/invercargill/value_type_matrix/uint64/buffer", () => {
+         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
+ 
+         var b = new Buffer<uint64?>(4);
+         for (int i = 0; i < 4; i++) b.set((uint)i, items[i]);
+         assert(b.count() == 4);
+         for (int i = 0; i < 4; i++) {
+             uint64? got;
+             assert(b.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+    });
+
+     Test.add_func("/invercargill/value_type_matrix/uint64/ring_buffer", () => {
+         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
+ 
+         var r = new RingBuffer<uint64?>(4);
+         for (int i = 0; i < 4; i++) r.set((uint)i, items[i]);
+         assert(r.count() == 4);
+         for (int i = 0; i < 4; i++) {
+             uint64? got;
+             assert(r.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+    });
 
     Test.add_func("/invercargill/value_type_matrix/uint64/series", () => {
         uint64?[] items = {5000000000UL, 1UL, 0UL, 18446744073709551615UL};
@@ -1411,55 +1399,49 @@ void value_type_matrix_uint64_tests() {
 }
 
 void value_type_matrix_float_tests() {
-    // BROKEN(/invercargill/value_type_matrix/float/vector): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/float/vector", () => {
-//         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};
-// 
-//         var v = new Vector<float?>();
-//         foreach (float? i in items) v.add(i);
-//         assert(v.count() == 4);
-//         assert(v.length == 4);
-//         for (int i = 0; i < 4; i++) {
-//             float? got;
-//             assert(v.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//         assert(v.to_array().length == 4);
-//         assert(v.to_vector().count() == 4);
-//         assert(v.first_or_default() == items[0]);
-//         assert(v.last_or_default() == items[3]);
-//     });
-
-    // BROKEN(/invercargill/value_type_matrix/float/buffer): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/float/buffer", () => {
-//         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};
-// 
-//         var b = new Buffer<float?>(4);
-//         for (int i = 0; i < 4; i++) b.set((uint)i, items[i]);
-//         assert(b.count() == 4);
-//         for (int i = 0; i < 4; i++) {
-//             float? got;
-//             assert(b.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//     });
-
-    // BROKEN(/invercargill/value_type_matrix/float/ring_buffer): known failure at time of writing -- whole case disabled.
-    // Keep the original body below for the fix tasks to re-enable:
-//     Test.add_func("/invercargill/value_type_matrix/float/ring_buffer", () => {
-//         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};
-// 
-//         var r = new RingBuffer<float?>(4);
-//         for (int i = 0; i < 4; i++) r.set((uint)i, items[i]);
-//         assert(r.count() == 4);
-//         for (int i = 0; i < 4; i++) {
-//             float? got;
-//             assert(r.try_get((uint)i, out got));
-//             assert(got == items[i]);
-//         }
-//     });
+     Test.add_func("/invercargill/value_type_matrix/float/vector", () => {
+         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};
+ 
+         var v = new Vector<float?>();
+         foreach (float? i in items) v.add(i);
+         assert(v.count() == 4);
+         assert(v.length == 4);
+         for (int i = 0; i < 4; i++) {
+             float? got;
+             assert(v.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+         assert(v.to_array().length == 4);
+         assert(v.to_vector().count() == 4);
+         assert(v.first_or_default() == items[0]);
+         assert(v.last_or_default() == items[3]);
+    });
+
+     Test.add_func("/invercargill/value_type_matrix/float/buffer", () => {
+         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};
+ 
+         var b = new Buffer<float?>(4);
+         for (int i = 0; i < 4; i++) b.set((uint)i, items[i]);
+         assert(b.count() == 4);
+         for (int i = 0; i < 4; i++) {
+             float? got;
+             assert(b.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+    });
+
+     Test.add_func("/invercargill/value_type_matrix/float/ring_buffer", () => {
+         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};
+ 
+         var r = new RingBuffer<float?>(4);
+         for (int i = 0; i < 4; i++) r.set((uint)i, items[i]);
+         assert(r.count() == 4);
+         for (int i = 0; i < 4; i++) {
+             float? got;
+             assert(r.try_get((uint)i, out got));
+             assert(got == items[i]);
+         }
+    });
 
     Test.add_func("/invercargill/value_type_matrix/float/series", () => {
         float?[] items = {1.5f, -2.25f, 100.5f, 0.0f};