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

Commitb87037b

Browse files
committed
Fix contrib/seg to be more wary of long input numbers.
seg stores the number of significant digits in an input numberin a "char" field. If char is signed, and the input is more than127 digits long, the count can read out as negative causingseg_out() to print garbage (or, if you're really unlucky,even crash).To fix, clamp the digit count to be not more than FLT_DIG.(In theory this loses some information about what the originalinput was, but it doesn't seem like useful information; it wouldnot survive dump/restore in any case.)Also, in case there are stored values of the seg type containingbad data, add a clamp in seg_out's restore() subroutine.Per bug #17725 from Robins Tharakan. It's been like thisforever, so back-patch to all supported branches.Discussion:https://postgr.es/m/17725-0a09313b67fbe86e@postgresql.org
1 parentae98deb commitb87037b

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

‎contrib/seg/expected/seg.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ SELECT '12.34567890123456'::seg AS seg;
256256
12.3457
257257
(1 row)
258258

259+
-- Same, with a very long input
260+
SELECT '12.3456789012345600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'::seg AS seg;
261+
seg
262+
---------
263+
12.3457
264+
(1 row)
265+
259266
-- Numbers with certainty indicators
260267
SELECT '~6.5'::seg AS seg;
261268
seg

‎contrib/seg/seg.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,9 +927,13 @@ restore(char *result, float val, int n)
927927

928928
/*
929929
* Put a cap on the number of significant digits to avoid garbage in the
930-
* output and ensure we don't overrun the result buffer.
930+
* output and ensure we don't overrun the result buffer. (n should not be
931+
* negative, but check to protect ourselves against corrupted data.)
931932
*/
932-
n=Min(n,FLT_DIG);
933+
if (n <=0)
934+
n=FLT_DIG;
935+
else
936+
n=Min(n,FLT_DIG);
933937

934938
/* remember the sign */
935939
sign= (val<0 ?1 :0);

‎contrib/seg/segparse.y

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include"postgres.h"
55

6+
#include<float.h>
67
#include<math.h>
78

89
#include"fmgr.h"
@@ -23,6 +24,8 @@
2324

2425
staticfloatseg_atof(constchar *value);
2526

27+
staticintsig_digits(constchar *value);
28+
2629
staticchar strbuf[25] = {
2730
'0','0','0','0','0',
2831
'0','0','0','0','0',
@@ -65,9 +68,9 @@ range: boundary PLUMIN deviation
6568
result->lower =$1.val -$3.val;
6669
result->upper =$1.val +$3.val;
6770
sprintf(strbuf,"%g", result->lower);
68-
result->l_sigd = Max(Min(6, significant_digits(strbuf)), Max($1.sigd,$3.sigd));
71+
result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd,$3.sigd));
6972
sprintf(strbuf,"%g", result->upper);
70-
result->u_sigd = Max(Min(6, significant_digits(strbuf)), Max($1.sigd,$3.sigd));
73+
result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd,$3.sigd));
7174
result->l_ext ='\0';
7275
result->u_ext ='\0';
7376
}
@@ -124,7 +127,7 @@ boundary: SEGFLOAT
124127
floatval = seg_atof($1);
125128

126129
$$.ext ='\0';
127-
$$.sigd =significant_digits($1);
130+
$$.sigd =sig_digits($1);
128131
$$.val = val;
129132
}
130133
|EXTENSIONSEGFLOAT
@@ -133,7 +136,7 @@ boundary: SEGFLOAT
133136
floatval = seg_atof($2);
134137

135138
$$.ext =$1[0];
136-
$$.sigd =significant_digits($2);
139+
$$.sigd =sig_digits($2);
137140
$$.val = val;
138141
}
139142
;
@@ -144,7 +147,7 @@ deviation: SEGFLOAT
144147
floatval = seg_atof($1);
145148

146149
$$.ext ='\0';
147-
$$.sigd =significant_digits($1);
150+
$$.sigd =sig_digits($1);
148151
$$.val = val;
149152
}
150153
;
@@ -161,5 +164,14 @@ seg_atof(const char *value)
161164
returnDatumGetFloat4(datum);
162165
}
163166

167+
staticint
168+
sig_digits(constchar *value)
169+
{
170+
intn =significant_digits(value);
171+
172+
/* Clamp, to ensure value will fit in sigd fields*/
173+
returnMin(n, FLT_DIG);
174+
}
175+
164176

165177
#include"segscan.c"

‎contrib/seg/sql/seg.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ SELECT '3.400e5'::seg AS seg;
6060
-- Digits truncated
6161
SELECT'12.34567890123456'::segAS seg;
6262

63+
-- Same, with a very long input
64+
SELECT'12.3456789012345600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'::segAS seg;
65+
6366
-- Numbers with certainty indicators
6467
SELECT'~6.5'::segAS seg;
6568
SELECT'<6.5'::segAS seg;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp