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

Commitc5321e9

Browse files
Add overflow checks to money type.
None of the arithmetic functions for the the money type handleoverflow. This commit introduces several helper functions withoverflow checking and makes use of them in the money type'sarithmetic functions.Fixes bug #18240.Reported-by: Alexander LakhinAuthor: Joseph KoshakowDiscussion:https://postgr.es/m/18240-c5da758d7dc1ecf0%40postgresql.orgDiscussion:https://postgr.es/m/CAAvxfHdBPOyEGS7s%2Bxf4iaW0-cgiq25jpYdWBqQqvLtLe_t6tw%40mail.gmail.comBackpatch-through: 12
1 parent5ee78e3 commitc5321e9

File tree

3 files changed

+124
-80
lines changed

3 files changed

+124
-80
lines changed

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

Lines changed: 94 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include"libpq/pqformat.h"
2727
#include"utils/builtins.h"
2828
#include"utils/cash.h"
29+
#include"utils/float.h"
2930
#include"utils/int8.h"
3031
#include"utils/numeric.h"
3132
#include"utils/pg_locale.h"
@@ -87,6 +88,82 @@ num_word(Cash value)
8788
returnbuf;
8889
}/* num_word() */
8990

91+
staticinlineCash
92+
cash_pl_cash(Cashc1,Cashc2)
93+
{
94+
Cashres;
95+
96+
if (unlikely(pg_add_s64_overflow(c1,c2,&res)))
97+
ereport(ERROR,
98+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
99+
errmsg("money out of range")));
100+
101+
returnres;
102+
}
103+
104+
staticinlineCash
105+
cash_mi_cash(Cashc1,Cashc2)
106+
{
107+
Cashres;
108+
109+
if (unlikely(pg_sub_s64_overflow(c1,c2,&res)))
110+
ereport(ERROR,
111+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
112+
errmsg("money out of range")));
113+
114+
returnres;
115+
}
116+
117+
staticinlineCash
118+
cash_mul_float8(Cashc,float8f)
119+
{
120+
float8res=rint(float8_mul((float8)c,f));
121+
122+
if (unlikely(isnan(res)|| !FLOAT8_FITS_IN_INT64(res)))
123+
ereport(ERROR,
124+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
125+
errmsg("money out of range")));
126+
127+
return (Cash)res;
128+
}
129+
130+
staticinlineCash
131+
cash_div_float8(Cashc,float8f)
132+
{
133+
float8res=rint(float8_div((float8)c,f));
134+
135+
if (unlikely(isnan(res)|| !FLOAT8_FITS_IN_INT64(res)))
136+
ereport(ERROR,
137+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
138+
errmsg("money out of range")));
139+
140+
return (Cash)res;
141+
}
142+
143+
staticinlineCash
144+
cash_mul_int64(Cashc,int64i)
145+
{
146+
Cashres;
147+
148+
if (unlikely(pg_mul_s64_overflow(c,i,&res)))
149+
ereport(ERROR,
150+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
151+
errmsg("money out of range")));
152+
153+
returnres;
154+
}
155+
156+
staticinlineCash
157+
cash_div_int64(Cashc,int64i)
158+
{
159+
if (unlikely(i==0))
160+
ereport(ERROR,
161+
(errcode(ERRCODE_DIVISION_BY_ZERO),
162+
errmsg("division by zero")));
163+
164+
returnc /i;
165+
}
166+
90167
/* cash_in()
91168
* Convert a string to a cash data type.
92169
* Format is [$]###[,]###[.##]
@@ -612,11 +689,8 @@ cash_pl(PG_FUNCTION_ARGS)
612689
{
613690
Cashc1=PG_GETARG_CASH(0);
614691
Cashc2=PG_GETARG_CASH(1);
615-
Cashresult;
616-
617-
result=c1+c2;
618692

619-
PG_RETURN_CASH(result);
693+
PG_RETURN_CASH(cash_pl_cash(c1,c2));
620694
}
621695

622696

@@ -628,11 +702,8 @@ cash_mi(PG_FUNCTION_ARGS)
628702
{
629703
Cashc1=PG_GETARG_CASH(0);
630704
Cashc2=PG_GETARG_CASH(1);
631-
Cashresult;
632-
633-
result=c1-c2;
634705

635-
PG_RETURN_CASH(result);
706+
PG_RETURN_CASH(cash_mi_cash(c1,c2));
636707
}
637708

638709

@@ -664,10 +735,8 @@ cash_mul_flt8(PG_FUNCTION_ARGS)
664735
{
665736
Cashc=PG_GETARG_CASH(0);
666737
float8f=PG_GETARG_FLOAT8(1);
667-
Cashresult;
668738

669-
result=rint(c*f);
670-
PG_RETURN_CASH(result);
739+
PG_RETURN_CASH(cash_mul_float8(c,f));
671740
}
672741

673742

@@ -679,10 +748,8 @@ flt8_mul_cash(PG_FUNCTION_ARGS)
679748
{
680749
float8f=PG_GETARG_FLOAT8(0);
681750
Cashc=PG_GETARG_CASH(1);
682-
Cashresult;
683751

684-
result=rint(f*c);
685-
PG_RETURN_CASH(result);
752+
PG_RETURN_CASH(cash_mul_float8(c,f));
686753
}
687754

688755

@@ -694,15 +761,8 @@ cash_div_flt8(PG_FUNCTION_ARGS)
694761
{
695762
Cashc=PG_GETARG_CASH(0);
696763
float8f=PG_GETARG_FLOAT8(1);
697-
Cashresult;
698764

699-
if (f==0.0)
700-
ereport(ERROR,
701-
(errcode(ERRCODE_DIVISION_BY_ZERO),
702-
errmsg("division by zero")));
703-
704-
result=rint(c /f);
705-
PG_RETURN_CASH(result);
765+
PG_RETURN_CASH(cash_div_float8(c,f));
706766
}
707767

708768

@@ -714,10 +774,8 @@ cash_mul_flt4(PG_FUNCTION_ARGS)
714774
{
715775
Cashc=PG_GETARG_CASH(0);
716776
float4f=PG_GETARG_FLOAT4(1);
717-
Cashresult;
718777

719-
result=rint(c* (float8)f);
720-
PG_RETURN_CASH(result);
778+
PG_RETURN_CASH(cash_mul_float8(c, (float8)f));
721779
}
722780

723781

@@ -729,10 +787,8 @@ flt4_mul_cash(PG_FUNCTION_ARGS)
729787
{
730788
float4f=PG_GETARG_FLOAT4(0);
731789
Cashc=PG_GETARG_CASH(1);
732-
Cashresult;
733790

734-
result=rint((float8)f*c);
735-
PG_RETURN_CASH(result);
791+
PG_RETURN_CASH(cash_mul_float8(c, (float8)f));
736792
}
737793

738794

@@ -745,15 +801,8 @@ cash_div_flt4(PG_FUNCTION_ARGS)
745801
{
746802
Cashc=PG_GETARG_CASH(0);
747803
float4f=PG_GETARG_FLOAT4(1);
748-
Cashresult;
749-
750-
if (f==0.0)
751-
ereport(ERROR,
752-
(errcode(ERRCODE_DIVISION_BY_ZERO),
753-
errmsg("division by zero")));
754804

755-
result=rint(c / (float8)f);
756-
PG_RETURN_CASH(result);
805+
PG_RETURN_CASH(cash_div_float8(c, (float8)f));
757806
}
758807

759808

@@ -765,10 +814,8 @@ cash_mul_int8(PG_FUNCTION_ARGS)
765814
{
766815
Cashc=PG_GETARG_CASH(0);
767816
int64i=PG_GETARG_INT64(1);
768-
Cashresult;
769817

770-
result=c*i;
771-
PG_RETURN_CASH(result);
818+
PG_RETURN_CASH(cash_mul_int64(c,i));
772819
}
773820

774821

@@ -780,10 +827,8 @@ int8_mul_cash(PG_FUNCTION_ARGS)
780827
{
781828
int64i=PG_GETARG_INT64(0);
782829
Cashc=PG_GETARG_CASH(1);
783-
Cashresult;
784830

785-
result=i*c;
786-
PG_RETURN_CASH(result);
831+
PG_RETURN_CASH(cash_mul_int64(c,i));
787832
}
788833

789834
/* cash_div_int8()
@@ -794,16 +839,8 @@ cash_div_int8(PG_FUNCTION_ARGS)
794839
{
795840
Cashc=PG_GETARG_CASH(0);
796841
int64i=PG_GETARG_INT64(1);
797-
Cashresult;
798-
799-
if (i==0)
800-
ereport(ERROR,
801-
(errcode(ERRCODE_DIVISION_BY_ZERO),
802-
errmsg("division by zero")));
803842

804-
result=c /i;
805-
806-
PG_RETURN_CASH(result);
843+
PG_RETURN_CASH(cash_div_int64(c,i));
807844
}
808845

809846

@@ -815,10 +852,8 @@ cash_mul_int4(PG_FUNCTION_ARGS)
815852
{
816853
Cashc=PG_GETARG_CASH(0);
817854
int32i=PG_GETARG_INT32(1);
818-
Cashresult;
819855

820-
result=c*i;
821-
PG_RETURN_CASH(result);
856+
PG_RETURN_CASH(cash_mul_int64(c, (int64)i));
822857
}
823858

824859

@@ -830,10 +865,8 @@ int4_mul_cash(PG_FUNCTION_ARGS)
830865
{
831866
int32i=PG_GETARG_INT32(0);
832867
Cashc=PG_GETARG_CASH(1);
833-
Cashresult;
834868

835-
result=i*c;
836-
PG_RETURN_CASH(result);
869+
PG_RETURN_CASH(cash_mul_int64(c, (int64)i));
837870
}
838871

839872

@@ -846,16 +879,8 @@ cash_div_int4(PG_FUNCTION_ARGS)
846879
{
847880
Cashc=PG_GETARG_CASH(0);
848881
int32i=PG_GETARG_INT32(1);
849-
Cashresult;
850-
851-
if (i==0)
852-
ereport(ERROR,
853-
(errcode(ERRCODE_DIVISION_BY_ZERO),
854-
errmsg("division by zero")));
855-
856-
result=c /i;
857882

858-
PG_RETURN_CASH(result);
883+
PG_RETURN_CASH(cash_div_int64(c, (int64)i));
859884
}
860885

861886

@@ -867,10 +892,8 @@ cash_mul_int2(PG_FUNCTION_ARGS)
867892
{
868893
Cashc=PG_GETARG_CASH(0);
869894
int16s=PG_GETARG_INT16(1);
870-
Cashresult;
871895

872-
result=c*s;
873-
PG_RETURN_CASH(result);
896+
PG_RETURN_CASH(cash_mul_int64(c, (int64)s));
874897
}
875898

876899
/* int2_mul_cash()
@@ -881,10 +904,8 @@ int2_mul_cash(PG_FUNCTION_ARGS)
881904
{
882905
int16s=PG_GETARG_INT16(0);
883906
Cashc=PG_GETARG_CASH(1);
884-
Cashresult;
885907

886-
result=s*c;
887-
PG_RETURN_CASH(result);
908+
PG_RETURN_CASH(cash_mul_int64(c, (int64)s));
888909
}
889910

890911
/* cash_div_int2()
@@ -896,15 +917,8 @@ cash_div_int2(PG_FUNCTION_ARGS)
896917
{
897918
Cashc=PG_GETARG_CASH(0);
898919
int16s=PG_GETARG_INT16(1);
899-
Cashresult;
900920

901-
if (s==0)
902-
ereport(ERROR,
903-
(errcode(ERRCODE_DIVISION_BY_ZERO),
904-
errmsg("division by zero")));
905-
906-
result=c /s;
907-
PG_RETURN_CASH(result);
921+
PG_RETURN_CASH(cash_div_int64(c, (int64)s));
908922
}
909923

910924
/* cashlarger()

‎src/test/regress/expected/money.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,3 +503,22 @@ SELECT '-92233720368547758.08'::money::numeric;
503503
-92233720368547758.08
504504
(1 row)
505505

506+
-- overflow checks
507+
SELECT '92233720368547758.07'::money + '0.01'::money;
508+
ERROR: money out of range
509+
SELECT '-92233720368547758.08'::money - '0.01'::money;
510+
ERROR: money out of range
511+
SELECT '92233720368547758.07'::money * 2::float8;
512+
ERROR: money out of range
513+
SELECT '-1'::money / 1.175494e-38::float4;
514+
ERROR: money out of range
515+
SELECT '92233720368547758.07'::money * 2::int4;
516+
ERROR: money out of range
517+
SELECT '1'::money / 0::int2;
518+
ERROR: division by zero
519+
SELECT '42'::money * 'inf'::float8;
520+
ERROR: money out of range
521+
SELECT '42'::money * '-inf'::float8;
522+
ERROR: money out of range
523+
SELECT '42'::money * 'nan'::float4;
524+
ERROR: money out of range

‎src/test/regress/sql/money.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,14 @@ SELECT '12345678901234567'::money::numeric;
129129
SELECT'-12345678901234567'::money::numeric;
130130
SELECT'92233720368547758.07'::money::numeric;
131131
SELECT'-92233720368547758.08'::money::numeric;
132+
133+
-- overflow checks
134+
SELECT'92233720368547758.07'::money+'0.01'::money;
135+
SELECT'-92233720368547758.08'::money-'0.01'::money;
136+
SELECT'92233720368547758.07'::money*2::float8;
137+
SELECT'-1'::money/1.175494e-38::float4;
138+
SELECT'92233720368547758.07'::money*2::int4;
139+
SELECT'1'::money/0::int2;
140+
SELECT'42'::money*'inf'::float8;
141+
SELECT'42'::money*'-inf'::float8;
142+
SELECT'42'::money*'nan'::float4;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp