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

Commit656df62

Browse files
committed
Add overflow checks to money type input function
The money type input function did not have any overflow checks at all.There were some regression tests that purported to check for overflow,but they actually checked for the overflow behavior of the int8 typebefore casting to money. Remove those unnecessary checks and add somethat actually check the money input function.Reviewed-by: Fabien COELHO <coelho@cri.ensmp.fr>
1 parent0dac5b5 commit656df62

File tree

3 files changed

+165
-16
lines changed

3 files changed

+165
-16
lines changed

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

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,30 @@ cash_in(PG_FUNCTION_ARGS)
189189
printf("cashin- string is '%s'\n",s);
190190
#endif
191191

192+
/*
193+
* We accumulate the absolute amount in "value" and then apply the sign at
194+
* the end. (The sign can appear before or after the digits, so it would
195+
* be more complicated to do otherwise.) Because of the larger range of
196+
* negative signed integers, we build "value" in the negative and then
197+
* flip the sign at the end, catching most-negative-number overflow if
198+
* necessary.
199+
*/
200+
192201
for (;*s;s++)
193202
{
194203
/* we look for digits as long as we have found less */
195204
/* than the required number of decimal places */
196205
if (isdigit((unsignedchar)*s)&& (!seen_dot||dec<fpoint))
197206
{
198-
value= (value*10)+ (*s-'0');
207+
Cashnewvalue= (value*10)- (*s-'0');
208+
209+
if (newvalue /10!=value)
210+
ereport(ERROR,
211+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
212+
errmsg("value \"%s\" is out of range for type money",
213+
str)));
214+
215+
value=newvalue;
199216

200217
if (seen_dot)
201218
dec++;
@@ -214,11 +231,27 @@ cash_in(PG_FUNCTION_ARGS)
214231

215232
/* round off if there's another digit */
216233
if (isdigit((unsignedchar)*s)&&*s >='5')
217-
value++;
234+
value--;/* remember we build the value in the negative */
235+
236+
if (value>0)
237+
ereport(ERROR,
238+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
239+
errmsg("value \"%s\" is out of range for type money",
240+
str)));
218241

219242
/* adjust for less than required decimal places */
220243
for (;dec<fpoint;dec++)
221-
value *=10;
244+
{
245+
Cashnewvalue=value*10;
246+
247+
if (newvalue /10!=value)
248+
ereport(ERROR,
249+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
250+
errmsg("value \"%s\" is out of range for type money",
251+
str)));
252+
253+
value=newvalue;
254+
}
222255

223256
/*
224257
* should only be trailing digits followed by whitespace, right paren,
@@ -247,7 +280,19 @@ cash_in(PG_FUNCTION_ARGS)
247280
str)));
248281
}
249282

250-
result=value*sgn;
283+
/* If the value is supposed to be positive, flip the sign, but check for
284+
* the most negative number. */
285+
if (sgn>0)
286+
{
287+
result=-value;
288+
if (result<0)
289+
ereport(ERROR,
290+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
291+
errmsg("value \"%s\" is out of range for type money",
292+
str)));
293+
}
294+
else
295+
result=value;
251296

252297
#ifdefCASHDEBUG
253298
printf("cashin- result is "INT64_FORMAT"\n",result);

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

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,96 @@ SELECT * FROM money_data;
185185
$123.46
186186
(1 row)
187187

188+
-- input checks
189+
SELECT '1234567890'::money;
190+
money
191+
-------------------
192+
$1,234,567,890.00
193+
(1 row)
194+
195+
SELECT '12345678901234567'::money;
196+
money
197+
----------------------------
198+
$12,345,678,901,234,567.00
199+
(1 row)
200+
201+
SELECT '123456789012345678'::money;
202+
ERROR: value "123456789012345678" is out of range for type money
203+
LINE 1: SELECT '123456789012345678'::money;
204+
^
205+
SELECT '9223372036854775807'::money;
206+
ERROR: value "9223372036854775807" is out of range for type money
207+
LINE 1: SELECT '9223372036854775807'::money;
208+
^
209+
SELECT '-12345'::money;
210+
money
211+
-------------
212+
-$12,345.00
213+
(1 row)
214+
215+
SELECT '-1234567890'::money;
216+
money
217+
--------------------
218+
-$1,234,567,890.00
219+
(1 row)
220+
221+
SELECT '-12345678901234567'::money;
222+
money
223+
-----------------------------
224+
-$12,345,678,901,234,567.00
225+
(1 row)
226+
227+
SELECT '-123456789012345678'::money;
228+
ERROR: value "-123456789012345678" is out of range for type money
229+
LINE 1: SELECT '-123456789012345678'::money;
230+
^
231+
SELECT '-9223372036854775808'::money;
232+
ERROR: value "-9223372036854775808" is out of range for type money
233+
LINE 1: SELECT '-9223372036854775808'::money;
234+
^
235+
-- special characters
236+
SELECT '(1)'::money;
237+
money
238+
--------
239+
-$1.00
240+
(1 row)
241+
242+
SELECT '($123,456.78)'::money;
243+
money
244+
--------------
245+
-$123,456.78
246+
(1 row)
247+
248+
-- documented minimums and maximums
249+
SELECT '-92233720368547758.08'::money;
250+
money
251+
-----------------------------
252+
-$92,233,720,368,547,758.08
253+
(1 row)
254+
255+
SELECT '92233720368547758.07'::money;
256+
money
257+
----------------------------
258+
$92,233,720,368,547,758.07
259+
(1 row)
260+
261+
SELECT '-92233720368547758.09'::money;
262+
ERROR: value "-92233720368547758.09" is out of range for type money
263+
LINE 1: SELECT '-92233720368547758.09'::money;
264+
^
265+
SELECT '92233720368547758.08'::money;
266+
ERROR: value "92233720368547758.08" is out of range for type money
267+
LINE 1: SELECT '92233720368547758.08'::money;
268+
^
269+
-- rounding
270+
SELECT '-92233720368547758.085'::money;
271+
ERROR: value "-92233720368547758.085" is out of range for type money
272+
LINE 1: SELECT '-92233720368547758.085'::money;
273+
^
274+
SELECT '92233720368547758.075'::money;
275+
ERROR: value "92233720368547758.075" is out of range for type money
276+
LINE 1: SELECT '92233720368547758.075'::money;
277+
^
188278
-- Cast int4/int8 to money
189279
SELECT 1234567890::money;
190280
money
@@ -198,10 +288,6 @@ SELECT 12345678901234567::money;
198288
$12,345,678,901,234,567.00
199289
(1 row)
200290

201-
SELECT 123456789012345678::money;
202-
ERROR: bigint out of range
203-
SELECT 9223372036854775807::money;
204-
ERROR: bigint out of range
205291
SELECT (-12345)::money;
206292
money
207293
-------------
@@ -220,10 +306,6 @@ SELECT (-12345678901234567)::money;
220306
-$12,345,678,901,234,567.00
221307
(1 row)
222308

223-
SELECT (-123456789012345678)::money;
224-
ERROR: bigint out of range
225-
SELECT (-9223372036854775808)::money;
226-
ERROR: bigint out of range
227309
SELECT 1234567890::int4::money;
228310
money
229311
-------------------

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,38 @@ DELETE FROM money_data;
5757
INSERT INTO money_dataVALUES ('$123.459');
5858
SELECT*FROM money_data;
5959

60+
-- input checks
61+
SELECT'1234567890'::money;
62+
SELECT'12345678901234567'::money;
63+
SELECT'123456789012345678'::money;
64+
SELECT'9223372036854775807'::money;
65+
SELECT'-12345'::money;
66+
SELECT'-1234567890'::money;
67+
SELECT'-12345678901234567'::money;
68+
SELECT'-123456789012345678'::money;
69+
SELECT'-9223372036854775808'::money;
70+
71+
-- special characters
72+
SELECT'(1)'::money;
73+
SELECT'($123,456.78)'::money;
74+
75+
-- documented minimums and maximums
76+
SELECT'-92233720368547758.08'::money;
77+
SELECT'92233720368547758.07'::money;
78+
79+
SELECT'-92233720368547758.09'::money;
80+
SELECT'92233720368547758.08'::money;
81+
82+
-- rounding
83+
SELECT'-92233720368547758.085'::money;
84+
SELECT'92233720368547758.075'::money;
85+
6086
-- Cast int4/int8 to money
6187
SELECT1234567890::money;
6288
SELECT12345678901234567::money;
63-
SELECT123456789012345678::money;
64-
SELECT9223372036854775807::money;
6589
SELECT (-12345)::money;
6690
SELECT (-1234567890)::money;
6791
SELECT (-12345678901234567)::money;
68-
SELECT (-123456789012345678)::money;
69-
SELECT (-9223372036854775808)::money;
7092
SELECT1234567890::int4::money;
7193
SELECT12345678901234567::int8::money;
7294
SELECT (-1234567890)::int4::money;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp