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

Commit701c881

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 parent33dd895 commit701c881

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
@@ -928,9 +928,13 @@ restore(char *result, float val, int n)
928928

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

935939
/* remember the sign */
936940
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"
@@ -20,6 +21,8 @@
2021

2122
staticfloatseg_atof(constchar *value);
2223

24+
staticintsig_digits(constchar *value);
25+
2326
staticchar strbuf[25] = {
2427
'0','0','0','0','0',
2528
'0','0','0','0','0',
@@ -62,9 +65,9 @@ range: boundary PLUMIN deviation
6265
result->lower =$1.val -$3.val;
6366
result->upper =$1.val +$3.val;
6467
sprintf(strbuf,"%g", result->lower);
65-
result->l_sigd = Max(Min(6, significant_digits(strbuf)), Max($1.sigd,$3.sigd));
68+
result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd,$3.sigd));
6669
sprintf(strbuf,"%g", result->upper);
67-
result->u_sigd = Max(Min(6, significant_digits(strbuf)), Max($1.sigd,$3.sigd));
70+
result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd,$3.sigd));
6871
result->l_ext ='\0';
6972
result->u_ext ='\0';
7073
}
@@ -121,7 +124,7 @@ boundary: SEGFLOAT
121124
floatval = seg_atof($1);
122125

123126
$$.ext ='\0';
124-
$$.sigd =significant_digits($1);
127+
$$.sigd =sig_digits($1);
125128
$$.val = val;
126129
}
127130
|EXTENSIONSEGFLOAT
@@ -130,7 +133,7 @@ boundary: SEGFLOAT
130133
floatval = seg_atof($2);
131134

132135
$$.ext =$1[0];
133-
$$.sigd =significant_digits($2);
136+
$$.sigd =sig_digits($2);
134137
$$.val = val;
135138
}
136139
;
@@ -141,7 +144,7 @@ deviation: SEGFLOAT
141144
floatval = seg_atof($1);
142145

143146
$$.ext ='\0';
144-
$$.sigd =significant_digits($1);
147+
$$.sigd =sig_digits($1);
145148
$$.val = val;
146149
}
147150
;
@@ -157,3 +160,12 @@ seg_atof(const char *value)
157160
datum =DirectFunctionCall1(float4in,CStringGetDatum(value));
158161
returnDatumGetFloat4(datum);
159162
}
163+
164+
staticint
165+
sig_digits(constchar *value)
166+
{
167+
intn =significant_digits(value);
168+
169+
/* Clamp, to ensure value will fit in sigd fields*/
170+
returnMin(n, FLT_DIG);
171+
}

‎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