From: Daniele Varrazzo Date: Mon, 16 May 2022 00:14:56 +0000 (+0200) Subject: fix: raise an exception if the struct package is affected by issue #304 X-Git-Tag: 3.1~92^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31574fdc42a721347dadb2ba9d55094757572c2c;p=thirdparty%2Fpsycopg.git fix: raise an exception if the struct package is affected by issue #304 Cowardly refuse to transform ones in zeros. --- diff --git a/psycopg/psycopg/_struct.py b/psycopg/psycopg/_struct.py index ba51164a4..d6c603cb6 100644 --- a/psycopg/psycopg/_struct.py +++ b/psycopg/psycopg/_struct.py @@ -8,6 +8,7 @@ import struct from typing import Callable, cast, Optional, Tuple from .abc import Buffer +from . import errors as e from ._compat import Protocol, TypeAlias PackInt: TypeAlias = Callable[[int], bytes] @@ -40,3 +41,15 @@ unpack_float8 = cast(UnpackFloat, struct.Struct("!d").unpack) _struct_len = struct.Struct("!i") pack_len = cast(Callable[[int], bytes], _struct_len.pack) unpack_len = cast(UnpackLen, _struct_len.unpack_from) + + +def pack_float4_bug_304(x: float) -> bytes: + raise e.InterfaceError( + "cannot dump Float4: Python affected by bug #304," + " see https://github.com/psycopg/psycopg/issues/304" + ) + + +# If issue #304 is detected, raise an error instead of dumping wrong data. +if struct.Struct("!f").pack(1.0) != bytes.fromhex("3f800000"): + pack_float4 = pack_float4_bug_304 diff --git a/tests/types/test_numeric.py b/tests/types/test_numeric.py index e75a43dae..8f3ac6ac3 100644 --- a/tests/types/test_numeric.py +++ b/tests/types/test_numeric.py @@ -569,6 +569,18 @@ def test_minus_minus_quote(conn, pgtype): assert result == 1 +@pytest.mark.parametrize("wrapper", "Int2 Int4 Int8 Oid Float4 Float8".split()) +@pytest.mark.parametrize("fmt_in", PyFormat) +def test_dump_wrapper(conn, wrapper, fmt_in): + wrapper = getattr(psycopg.types.numeric, wrapper) + obj = wrapper(1) + cur = conn.execute( + f"select %(obj){fmt_in.value} = 1, %(obj){fmt_in.value}", {"obj": obj} + ) + rec = cur.fetchone() + assert rec[0], rec[1] + + @pytest.mark.parametrize("wrapper", "Int2 Int4 Int8 Oid Float4 Float8".split()) def test_dump_wrapper_oid(wrapper): wrapper = getattr(psycopg.types.numeric, wrapper)