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

Commitd35f1d4

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 parente39856d commitd35f1d4

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',
@@ -63,9 +66,9 @@ range: boundary PLUMIN deviation
6366
result->lower =$1.val -$3.val;
6467
result->upper =$1.val +$3.val;
6568
sprintf(strbuf,"%g", result->lower);
66-
result->l_sigd = Max(Min(6, significant_digits(strbuf)), Max($1.sigd,$3.sigd));
69+
result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd,$3.sigd));
6770
sprintf(strbuf,"%g", result->upper);
68-
result->u_sigd = Max(Min(6, significant_digits(strbuf)), Max($1.sigd,$3.sigd));
71+
result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd,$3.sigd));
6972
result->l_ext ='\0';
7073
result->u_ext ='\0';
7174
}
@@ -122,7 +125,7 @@ boundary: SEGFLOAT
122125
float val = seg_atof($1);
123126

124127
$$.ext ='\0';
125-
$$.sigd =significant_digits($1);
128+
$$.sigd =sig_digits($1);
126129
$$.val = val;
127130
}
128131
|EXTENSIONSEGFLOAT
@@ -131,7 +134,7 @@ boundary: SEGFLOAT
131134
float val = seg_atof($2);
132135

133136
$$.ext =$1[0];
134-
$$.sigd =significant_digits($2);
137+
$$.sigd =sig_digits($2);
135138
$$.val = val;
136139
}
137140
;
@@ -142,7 +145,7 @@ deviation: SEGFLOAT
142145
float val = seg_atof($1);
143146

144147
$$.ext ='\0';
145-
$$.sigd =significant_digits($1);
148+
$$.sigd =sig_digits($1);
146149
$$.val = val;
147150
}
148151
;
@@ -159,5 +162,14 @@ seg_atof(const char *value)
159162
returnDatumGetFloat4(datum);
160163
}
161164

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

163175
#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