Skip to content

Commit

Permalink
Erroring on constructing an odd length hex byte string (#539)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahangsu authored Sep 20, 2022
1 parent 508b133 commit 53c8e00
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 12 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Unreleased

## Fixed
* Erroring on constructing an odd length hex string. ([#539](https://github.com/algorand/pyteal/pull/539))

# 0.18.1

## Fixed
Expand Down
22 changes: 10 additions & 12 deletions pyteal/ast/bytes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Union, cast, overload, TYPE_CHECKING
from typing import cast, overload, TYPE_CHECKING

from pyteal.types import TealType, valid_base16, valid_base32, valid_base64
from pyteal.util import escapeStr
Expand All @@ -14,14 +14,14 @@ class Bytes(LeafExpr):
"""An expression that represents a byte string."""

@overload
def __init__(self, arg1: Union[str, bytes, bytearray]) -> None:
def __init__(self, arg1: str | bytes | bytearray) -> None:
pass

@overload
def __init__(self, arg1: str, arg2: str) -> None:
pass

def __init__(self, arg1: Union[str, bytes, bytearray], arg2: str = None) -> None:
def __init__(self, arg1: str | bytes | bytearray, arg2: str = None) -> None:
"""
__init__(arg1: Union[str, bytes, bytearray]) -> None
__init__(self, arg1: str, arg2: str) -> None
Expand Down Expand Up @@ -49,15 +49,15 @@ def __init__(self, arg1: Union[str, bytes, bytearray], arg2: str = None) -> None
self.byte_str = escapeStr(arg1)
elif type(arg1) in (bytes, bytearray):
self.base = "base16"
self.byte_str = cast(Union[bytes, bytearray], arg1).hex()
self.byte_str = cast(bytes | bytearray, arg1).hex()
else:
raise TealInputError("Unknown argument type: {}".format(type(arg1)))
raise TealInputError(f"Unknown argument type: {type(arg1)}")
else:
if type(arg1) is not str:
raise TealInputError("Unknown type for base: {}".format(type(arg1)))
raise TealInputError(f"Unknown type for base: {type(arg1)}")

if type(arg2) is not str:
raise TealInputError("Unknown type for value: {}".format(type(arg2)))
raise TealInputError(f"Unknown type for value: {type(arg2)}")

self.base = arg1

Expand All @@ -75,9 +75,7 @@ def __init__(self, arg1: Union[str, bytes, bytearray], arg2: str = None) -> None
valid_base16(self.byte_str)
else:
raise TealInputError(
"invalid base {}, need to be base32, base64, or base16.".format(
self.base
)
f"invalid base {self.base}, need to be base32, base64, or base16."
)

def __teal__(self, options: "CompileOptions"):
Expand All @@ -86,12 +84,12 @@ def __teal__(self, options: "CompileOptions"):
elif self.base == "base16":
payload = "0x" + self.byte_str
else:
payload = "{}({})".format(self.base, self.byte_str)
payload = f"{self.base}({self.byte_str})"
op = TealOp(self, Op.byte, payload)
return TealBlock.FromOp(options, op)

def __str__(self):
return "({} bytes: {})".format(self.base, self.byte_str)
return f"({self.base} bytes: {self.byte_str})"

def type_of(self):
return TealType.bytes
Expand Down
10 changes: 10 additions & 0 deletions pyteal/ast/bytes_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest

import pyteal as pt
from pyteal.errors import TealInputError

options = pt.CompileOptions()

Expand Down Expand Up @@ -88,6 +89,15 @@ def test_bytes_base16_empty():
assert actual == expected


B16_ODD_LEN_TESTCASES = ["F", "0c1"]


@pytest.mark.parametrize("testcase", B16_ODD_LEN_TESTCASES)
def test_bytes_base16_odd_len(testcase):
with pytest.raises(TealInputError):
pt.Bytes("base16", testcase)


def test_bytes_utf8():
expr = pt.Bytes("hello world")
assert expr.type_of() == pt.TealType.bytes
Expand Down
5 changes: 5 additions & 0 deletions pyteal/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ def valid_base64(s: str):

def valid_base16(s: str):
"""check if s is a valid hex encoding string"""
if len(s) % 2:
raise TealInputError(
f"{s} is of odd length, not a valid RFC 4648 base16 string"
)

pattern = re.compile(r"[0-9A-Fa-f]*")

if pattern.fullmatch(s) is None:
Expand Down

0 comments on commit 53c8e00

Please sign in to comment.