From 4e8e00ffe733b1b65055f2355d6a538334449e6d Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Mon, 28 Oct 2024 12:14:00 +0000 Subject: [PATCH] feat: restrict result tag sizes to 256 bytes (#596) Closes #595 --- guppylang/prelude/_internal/checker.py | 8 ++++++++ tests/error/misc_errors/result_tag_too_big.err | 7 +++++++ tests/error/misc_errors/result_tag_too_big.py | 11 +++++++++++ 3 files changed, 26 insertions(+) create mode 100644 tests/error/misc_errors/result_tag_too_big.err create mode 100644 tests/error/misc_errors/result_tag_too_big.py diff --git a/guppylang/prelude/_internal/checker.py b/guppylang/prelude/_internal/checker.py index a7bc400a..e6d30d82 100644 --- a/guppylang/prelude/_internal/checker.py +++ b/guppylang/prelude/_internal/checker.py @@ -233,6 +233,10 @@ def check(self, args: list[ast.expr], ty: Type) -> tuple[ast.expr, Subst]: raise InternalGuppyError(f"Invalid array type args: {type_args}") +#: Maximum length of a tag in the `result` function. +TAG_MAX_LEN = 200 + + class ResultChecker(CustomCallChecker): """Call checker for the `result` function.""" @@ -241,6 +245,10 @@ def synthesize(self, args: list[ast.expr]) -> tuple[ast.expr, Type]: [tag, value] = args if not isinstance(tag, ast.Constant) or not isinstance(tag.value, str): raise GuppyTypeError("Expected a string literal", tag) + if len(tag.value.encode("utf-8")) > TAG_MAX_LEN: + raise GuppyTypeError( + f"Tag is too long, limited to {TAG_MAX_LEN} bytes", tag + ) value, ty = ExprSynthesizer(self.ctx).synthesize(value) # We only allow numeric values or vectors of numeric values err = ( diff --git a/tests/error/misc_errors/result_tag_too_big.err b/tests/error/misc_errors/result_tag_too_big.err new file mode 100644 index 00000000..7626cab2 --- /dev/null +++ b/tests/error/misc_errors/result_tag_too_big.err @@ -0,0 +1,7 @@ +Guppy compilation failed. Error in file $FILE:11 + +9: def foo(y: bool) -> None: +10: # each tick or cross is 3 bytes. The cross sends the tag over the limit. +11: result("✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅❌", y) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +GuppyTypeError: Tag is too long, limited to 200 bytes diff --git a/tests/error/misc_errors/result_tag_too_big.py b/tests/error/misc_errors/result_tag_too_big.py new file mode 100644 index 00000000..105b5bba --- /dev/null +++ b/tests/error/misc_errors/result_tag_too_big.py @@ -0,0 +1,11 @@ +from guppylang.prelude.builtins import result, py +from tests.util import compile_guppy + +# TODO use this once https://github.com/CQCL/guppylang/issues/599 lands +# from guppylang.prelude._internal.checker import TAG_MAX_LEN +# BIG_TAG = "a" * (TAG_MAX_LEN + 1) + +@compile_guppy +def foo(y: bool) -> None: + # each tick or cross is 3 bytes. The cross sends the tag over the limit. + result("✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅❌", y)