From 1af26e792ce1c488032b37c1a4fbd92648b6eb9e Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 8 Jan 2020 15:03:47 -0500 Subject: [PATCH] Fix errors in numeric binary decoder The size of the output buffer in numeric decoder is computed incorrectly which may lead to stack corruption or access to unitialized memory. This also fixes incorrect rendering of trailing zeros in some cases. Fixes: #520 Fixes: #514 --- asyncpg/pgproto | 2 +- tests/test_codecs.py | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/asyncpg/pgproto b/asyncpg/pgproto index 484e3520..41889cf6 160000 --- a/asyncpg/pgproto +++ b/asyncpg/pgproto @@ -1 +1 @@ -Subproject commit 484e3520d8cb0514b7596a8f9eaa80f3f7b79d0c +Subproject commit 41889cf651b36fe91df20ec6c0a25f306fcc48e8 diff --git a/tests/test_codecs.py b/tests/test_codecs.py index 1299f2bd..abd3c668 100644 --- a/tests/test_codecs.py +++ b/tests/test_codecs.py @@ -69,7 +69,6 @@ def _system_timezone(): decimal.Decimal("-1.00000000000000"), decimal.Decimal("-2.00000000000000"), decimal.Decimal("1000000000000000.00000000000000"), - decimal.Decimal("-0.00000000000000"), decimal.Decimal(1234), decimal.Decimal(-1234), decimal.Decimal("1234000000.00088883231"), @@ -111,7 +110,7 @@ def _system_timezone(): decimal.Decimal("0.0"), decimal.Decimal("-1.0"), decimal.Decimal("1.0E-1000"), - decimal.Decimal("1.0E1000"), + decimal.Decimal("1E1000"), decimal.Decimal("0.000000000000000000000000001"), decimal.Decimal("0.000000000000010000000000001"), decimal.Decimal("0.00000000000000000000000001"), @@ -141,6 +140,16 @@ def _system_timezone(): decimal.Decimal("0.001"), decimal.Decimal("0.01"), decimal.Decimal("0.1"), + decimal.Decimal("0.10"), + decimal.Decimal("0.100"), + decimal.Decimal("0.1000"), + decimal.Decimal("0.10000"), + decimal.Decimal("0.100000"), + decimal.Decimal("0.00001000"), + decimal.Decimal("0.000010000"), + decimal.Decimal("0.0000100000"), + decimal.Decimal("0.00001000000"), + decimal.Decimal("1" + "0" * 117 + "." + "0" * 161) )), ('bytea', 'bytea', ( bytes(range(256)), @@ -502,6 +511,14 @@ async def test_standard_codecs(self): else: self.assertEqual(result, outputval, err_msg) + if (typname == 'numeric' and + isinstance(inputval, decimal.Decimal)): + self.assertEqual( + result.as_tuple(), + outputval.as_tuple(), + err_msg, + ) + with self.subTest(sample=None, typname=typname): # Test that None is handled for all types. rsample = await st.fetchval(None)