diff --git a/protovalidate/internal/extra_func.py b/protovalidate/internal/extra_func.py index 12f368fd..d633dba4 100644 --- a/protovalidate/internal/extra_func.py +++ b/protovalidate/internal/extra_func.py @@ -653,8 +653,11 @@ def __address_part(self) -> bool: return False - if self.__h16(): - continue + try: + if self.__h16(): + continue + except ValueError: + return False if self.__take(":"): if self.__take(":"): @@ -666,6 +669,9 @@ def __address_part(self) -> bool: if self.__take(":"): return False + elif self._index == 1 or self._index == len(self._string): + # invalid - string cannot start or end on single colon + return False continue @@ -734,7 +740,11 @@ def __h16(self) -> bool: h16 = 1*4HEXDIG - Stores 16-bit value in _pieces. + If 1-4 hex digits are found, the parsed 16-bit unsigned integer is stored + in pieces and True is returned. + If 0 hex digits are found, returns False. + If more than 4 hex digits are found or the found hex digits cannot be + converted to an int, a ValueError is raised. """ start = self._index @@ -746,23 +756,24 @@ def __h16(self) -> bool: string = self._string[start : self._index] if len(string) == 0: - # too short + # too short, just return false + # this is not an error condition, it just means we didn't find any + # hex digits at the current position. return False if len(string) > 4: # too long - return False - - try: - value = int(string, 16) + # this is an error condition, it means we found a string of more than + # four valid hex digits, which is invalid in ipv6 addresses. + raise ValueError - self._pieces.append(value) + # Note that this will raise a ValueError also if string cannot be + # converted to an int. + value = int(string, 16) - return True + self._pieces.append(value) - except ValueError: - # Error converting to number - return False + return True def __hex_dig(self) -> bool: """Determine whether the current position is a hex digit. diff --git a/tests/conformance/nonconforming.yaml b/tests/conformance/nonconforming.yaml index fb2876bb..25744e50 100644 --- a/tests/conformance/nonconforming.yaml +++ b/tests/conformance/nonconforming.yaml @@ -7,25 +7,3 @@ standard_constraints/well_known_types/duration: standard_constraints/well_known_types/timestamp: - gte_lte/invalid/above - lte/invalid - -library/is_ip: - - version/omitted/invalid/ipv6/g - # input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:":0::0"} - # want: validation error (1 violation) - # 1. constraint_id: "library.is_ip" - # got: valid - - version/omitted/invalid/ipv6/h - # input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:"0::0:"} - # want: validation error (1 violation) - # 1. constraint_id: "library.is_ip" - # got: valid - - version/omitted/invalid/ipv6/i - # input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:"0::0:"} - # want: validation error (1 violation) - # 1. constraint_id: "library.is_ip" - # got: valid - - version/omitted/invalid/ipv6/j - # input: [type.googleapis.com/buf.validate.conformance.cases.IsIp]:{val:"::0000ffff"} - # want: validation error (1 violation) - # 1. constraint_id: "library.is_ip" - # got: unexpected error: string index out of range