diff --git a/.release-notes/3675.md b/.release-notes/3675.md new file mode 100644 index 0000000000..100657a487 --- /dev/null +++ b/.release-notes/3675.md @@ -0,0 +1,3 @@ +## Fix memory safety problem with Array.from_cpointer + +Previously, the `from_cpointer` method in arrays would trust the user to pass a valid pointer. This created an issue where the user could pass a null pointer using `Pointer.create`, leading to a situation where memory safety could be violated by trying to access an element of the array. This change makes it safe to pass a null pointer to `from_cpointer`, which will create a zero-length array. diff --git a/packages/builtin/array.pony b/packages/builtin/array.pony index 1b1f75cf62..b526c7b9b1 100644 --- a/packages/builtin/array.pony +++ b/packages/builtin/array.pony @@ -126,12 +126,16 @@ class Array[A] is Seq[A] Create an array from a C-style pointer and length. The contents are not copied. """ - _size = len - - if alloc > len then - _alloc = alloc + if ptr.is_null() then + _size = 0 + _alloc = 0 else - _alloc = len + _size = len + if alloc > len then + _alloc = alloc + else + _alloc = len + end end _ptr = ptr diff --git a/packages/builtin_test/_test.pony b/packages/builtin_test/_test.pony index b1278f3109..f6afe85b40 100644 --- a/packages/builtin_test/_test.pony +++ b/packages/builtin_test/_test.pony @@ -54,6 +54,7 @@ actor Main is TestList test(_TestStringUnchop) test(_TestStringRepeatStr) test(_TestStringConcatOffsetLen) + test(_TestStringFromCPointer) test(_TestSpecialValuesF32) test(_TestSpecialValuesF64) test(_TestArrayAppend) @@ -68,6 +69,7 @@ actor Main is TestList test(_TestArraySwapElements) test(_TestArrayChop) test(_TestArrayUnchop) + test(_TestArrayFromCPointer) test(_TestMath128) test(_TestRem) test(_TestMod) @@ -1275,6 +1277,16 @@ class iso _TestStringConcatOffsetLen is UnitTest fun apply(h: TestHelper) => h.assert_eq[String](recover String.>concat("ABCD".values(), 1, 2) end, "BC") +class iso _TestStringFromCPointer is UnitTest + """ + Test creating a string from a pointer + """ + fun name(): String => "builtin/String.from_cpointer" + + fun apply(h: TestHelper) => + let str = String.from_cpointer(Pointer[U8], 1, 1) + h.assert_eq[USize](0, str.size()) + class iso _TestArrayAppend is UnitTest fun name(): String => "builtin/Array.append" @@ -1681,6 +1693,16 @@ class iso _TestArrayUnchop is UnitTest error end +class iso _TestArrayFromCPointer is UnitTest + """ + Test creating an array from a pointer + """ + fun name(): String => "builtin/Array.from_cpointer" + + fun apply(h: TestHelper) => + let arr = Array[U8].from_cpointer(Pointer[U8], 1, 1) + h.assert_eq[USize](0, arr.size()) + class iso _TestMath128 is UnitTest """ Test 128 bit integer math.