From 3c66fb7889f116f2fd732c4d58f0bd2b1ec347aa Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 20 Aug 2023 10:51:33 +0100 Subject: [PATCH] Fix stack corruption when function returns pointer to its argument --- NEWS.md | 2 ++ src/vcode.c | 9 ++++++++- test/regress/func25.vhd | 37 +++++++++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/regress/func25.vhd diff --git a/NEWS.md b/NEWS.md index 14794f9f..dca5d038 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,8 @@ instantiated the package (#750). - Improved checking for configuration specifications. - Empty bit string literals are now parsed correctly. +- Fixed stack corruption when a function returns an alias of one of its + array arguments. ## Version 1.10.1 - 2023-07-28 - Fixed incorrect sensitivity list generation with concurrent statements diff --git a/src/vcode.c b/src/vcode.c index 281dac4e..9adffe69 100644 --- a/src/vcode.c +++ b/src/vcode.c @@ -379,6 +379,7 @@ void vcode_heap_allocate(vcode_reg_t reg) case VCODE_OP_ADDRESS_OF: case VCODE_OP_LINK_VAR: case VCODE_OP_LINK_PACKAGE: + case VCODE_OP_CONTEXT_UPREF: break; case VCODE_OP_ALLOC: @@ -445,7 +446,13 @@ void vcode_heap_allocate(vcode_reg_t reg) break; case VCODE_OP_FCALL: - // Must have been safety checked by definition + for (int i = 0; i < defn->args.count; i++) { + const vtype_kind_t rkind = vcode_reg_kind(reg); + if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) { + // Function may return a pointer to its argument + vcode_heap_allocate(defn->args.items[i]); + } + } break; case VCODE_OP_RECORD_REF: diff --git a/test/regress/func25.vhd b/test/regress/func25.vhd new file mode 100644 index 00000000..8724117b --- /dev/null +++ b/test/regress/func25.vhd @@ -0,0 +1,37 @@ +entity func25 is +end entity; + +architecture test of func25 is + + function change_bounds (s : string; l, r : positive) return string is + alias ss : string(l to r) is s; + begin + return ss; + end function; + + impure function get_string (c : character) return string is + variable s : string(1 to 15); + begin + s := "hello, world! " & c; + return change_bounds(s, 101, 115); -- Returns a pointer to S + end function; + + function get_left (s : string) return positive is + begin + return s'left; + end function; + + signal c : character := 'x'; + +begin + + p1: process is + begin + wait for 1 ns; + report get_string(c); + assert get_string(c) = "hello, world! x"; + assert get_left(get_string(c)) = 101; + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 8dea1e2e..63266ed1 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -825,3 +825,4 @@ predef4 normal,2008 issue744 normal,vhpi issue747 fail,gold,gL=10 vhpi9 normal,vhpi +func25 normal -- 2.39.2