Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2e3cc39

Browse files
committed
Guard against bad "dscale" values in numeric_recv().
We were not checking to see if the supplied dscale was valid for the givendigit array when receiving binary-format numeric values. While dscale canvalidly be more than the number of nonzero fractional digits, it shouldn'tbe less; that case causes fractional digits to be hidden on display eventhough they're there and participate in arithmetic.Bug #12053 from Tommaso Sala indicates that there's at least one brokenclient library out there that sometimes supplies an incorrect dscale value,leading to strange behavior. This suggests that simply throwing an errormight not be the best response; it would lead to failures in applicationsthat might seem to be working fine today. What seems the least risky fixis to truncate away any digits that would be hidden by dscale. Thispreserves the existing behavior in terms of what will be printed for thetransmitted value, while preventing subsequent arithmetic from producingresults inconsistent with that.In passing, throw a specific error for the case of dscale being outsidethe range that will fit into a numeric's header. Before you got "valueoverflows numeric format", which is a bit misleading.Back-patch to all supported branches.
1 parentc2be18c commit2e3cc39

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

‎src/backend/utils/adt/numeric.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,8 @@ numeric_recv(PG_FUNCTION_ARGS)
655655
alloc_var(&value,len);
656656

657657
value.weight= (int16)pq_getmsgint(buf,sizeof(int16));
658+
/* we allow any int16 for weight --- OK? */
659+
658660
value.sign= (uint16)pq_getmsgint(buf,sizeof(uint16));
659661
if (!(value.sign==NUMERIC_POS||
660662
value.sign==NUMERIC_NEG||
@@ -664,6 +666,11 @@ numeric_recv(PG_FUNCTION_ARGS)
664666
errmsg("invalid sign in external \"numeric\" value")));
665667

666668
value.dscale= (uint16)pq_getmsgint(buf,sizeof(uint16));
669+
if ((value.dscale&NUMERIC_DSCALE_MASK)!=value.dscale)
670+
ereport(ERROR,
671+
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
672+
errmsg("invalid scale in external \"numeric\" value")));
673+
667674
for (i=0;i<len;i++)
668675
{
669676
NumericDigitd=pq_getmsgint(buf,sizeof(NumericDigit));
@@ -675,6 +682,14 @@ numeric_recv(PG_FUNCTION_ARGS)
675682
value.digits[i]=d;
676683
}
677684

685+
/*
686+
* If the given dscale would hide any digits, truncate those digits away.
687+
* We could alternatively throw an error, but that would take a bunch of
688+
* extra code (about as much as trunc_var involves), and it might cause
689+
* client compatibility issues.
690+
*/
691+
trunc_var(&value,value.dscale);
692+
678693
apply_typmod(&value,typmod);
679694

680695
res=make_result(&value);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp