diff --git a/tests/functional/builtins/codegen/test_concat.py b/tests/functional/builtins/codegen/test_concat.py index 5558138551..7354515989 100644 --- a/tests/functional/builtins/codegen/test_concat.py +++ b/tests/functional/builtins/codegen/test_concat.py @@ -55,6 +55,70 @@ def krazykonkat(z: Bytes[10]) -> Bytes[25]: print("Passed third concat test") +def test_concat_buffer(get_contract): + # GHSA-2q8v-3gqq-4f8p + code = """ +@internal +def bar() -> uint256: + sss: String[2] = concat("a", "b") + return 1 + + +@external +def foo() -> int256: + a: int256 = -1 + b: uint256 = self.bar() + return a + """ + c = get_contract(code) + assert c.foo() == -1 + + +def test_concat_buffer2(get_contract): + # GHSA-2q8v-3gqq-4f8p + code = """ +i: immutable(int256) + +@external +def __init__(): + i = -1 + s: String[2] = concat("a", "b") + +@external +def foo() -> int256: + return i + """ + c = get_contract(code) + assert c.foo() == -1 + + +def test_concat_buffer3(get_contract): + # GHSA-2q8v-3gqq-4f8p + code = """ +s: String[1] +s2: String[33] +s3: String[34] + +@external +def __init__(): + self.s = "a" + self.s2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # 33*'a' + +@internal +def bar() -> uint256: + self.s3 = concat(self.s, self.s2) + return 1 + +@external +def foo() -> int256: + i: int256 = -1 + b: uint256 = self.bar() + return i + """ + c = get_contract(code) + assert c.foo() == -1 + + def test_concat_bytes32(get_contract_with_gas_estimation): test_concat_bytes32 = """ @external diff --git a/vyper/builtins/functions.py b/vyper/builtins/functions.py index 4f8101dfbe..8ee6f5fd76 100644 --- a/vyper/builtins/functions.py +++ b/vyper/builtins/functions.py @@ -543,13 +543,12 @@ def build_IR(self, expr, context): else: ret_typ = BytesT(dst_maxlen) + # respect API of copy_bytes + bufsize = dst_maxlen + 32 + buf = context.new_internal_variable(BytesT(bufsize)) + # Node representing the position of the output in memory - dst = IRnode.from_list( - context.new_internal_variable(ret_typ), - typ=ret_typ, - location=MEMORY, - annotation="concat destination", - ) + dst = IRnode.from_list(buf, typ=ret_typ, location=MEMORY, annotation="concat destination") ret = ["seq"] # stack item representing our current offset in the dst buffer