From cc071dc53a65ee55caa576e3d12ecfee6674ced1 Mon Sep 17 00:00:00 2001 From: Sean T Allen Date: Sat, 1 Jul 2017 18:04:45 -0400 Subject: [PATCH] Fix segfault in Array.trim_in_place This is the mirror update to Array.trim_in_place that was made previously in String. Relevant commit comment from String: Array.trim_in_place wasn't written to work correctly if you were to trim the array down to nothing and then append a size less than the "alloc" value that is left. This combination could result in incorrect handling for arrays that end up with a size of 0. This is because, a new pointer was created, but we retained incorrect alloc info. This wouldn't cause an error so long as when you used the array for something like an append, reserve allocated new memory. However, if the appended value was less than the perceived alloc size, no additional memory would be added and kaboom. see 381b2816c6581dd2441f879d81ed9890ca181f4e --- packages/builtin/array.pony | 2 +- packages/builtin_test/_test.pony | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/builtin/array.pony b/packages/builtin/array.pony index 1805602d19..aca543c209 100644 --- a/packages/builtin/array.pony +++ b/packages/builtin/array.pony @@ -186,7 +186,7 @@ class Array[A] is Seq[A] _size = last - offset _alloc = _alloc - offset - _ptr = if _size > 0 then _ptr._offset(offset) else _ptr.create() end + _ptr = _ptr._offset(offset) fun val trim(from: USize = 0, to: USize = -1): Array[A] val => """ diff --git a/packages/builtin_test/_test.pony b/packages/builtin_test/_test.pony index 16e4fe8ee3..e4482b442d 100644 --- a/packages/builtin_test/_test.pony +++ b/packages/builtin_test/_test.pony @@ -56,6 +56,7 @@ actor Main is TestList test(_TestArraySlice) test(_TestArrayTrim) test(_TestArrayTrimInPlace) + test(_TestArrayTrimInPlaceWithAppend) test(_TestArrayInsert) test(_TestArrayValuesRewind) test(_TestArrayFind) @@ -1169,6 +1170,26 @@ class iso _TestArrayTrimInPlace is UnitTest copy.trim_in_place(from, to) h.assert_array_eq[U8](expected, copy) +class iso _TestArrayTrimInPlaceWithAppend is UnitTest + """ + Test trimming part of a array in place then append and trim again + + Verifies we don't get a segfault similar to String and... + https://github.com/ponylang/ponyc/issues/1996 + """ + fun name(): String => "builtin/Array.trim_in_place_with_append" + + fun apply(h: TestHelper) => + let a: Array[U8] = [0; 1; 2; 3; 4; 5; 6] + let big: Array[U8] val = recover val Array[U8].init(U8(1), 12_000) end + a.trim_in_place(a.size()) + h.assert_array_eq[U8](Array[U8], a) + a.append(big) + a.trim_in_place(a.size()) + h.assert_array_eq[U8](Array[U8], a) + a.append([as U8: 0; 10]) + h.assert_array_eq[U8]([as U8: 0; 10], a) + class iso _TestArrayInsert is UnitTest """ Test inserting new element into array