Skip to content

Commit b081fe4

Browse files
committed
Fix corner case bug in numeric to_char() some more.
The band-aid applied in commit f0bedf3 turns out to still need some work: it made sure we didn't set Np->last_relevant too small (to the left of the decimal point), but it didn't prevent setting it too large (off the end of the partially-converted string). This could result in fetching data beyond the end of the allocated space, which with very bad luck could cause a SIGSEGV, though I don't see any hazard of interesting memory disclosure. Per bug #17839 from Thiago Nunes. The bug's pretty ancient, so back-patch to all supported versions. Discussion: https://postgr.es/m/17839-aada50db24d7b0da@postgresql.org
1 parent a563c24 commit b081fe4

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5695,13 +5695,20 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
56955695

56965696
/*
56975697
* If any '0' specifiers are present, make sure we don't strip
5698-
* those digits.
5698+
* those digits. But don't advance last_relevant beyond the last
5699+
* character of the Np->number string, which is a hazard if the
5700+
* number got shortened due to precision limitations.
56995701
*/
57005702
if (Np->last_relevant && Np->Num->zero_end > Np->out_pre_spaces)
57015703
{
5704+
int last_zero_pos;
57025705
char *last_zero;
57035706

5704-
last_zero = Np->number + (Np->Num->zero_end - Np->out_pre_spaces);
5707+
/* note that Np->number cannot be zero-length here */
5708+
last_zero_pos = strlen(Np->number) - 1;
5709+
last_zero_pos = Min(last_zero_pos,
5710+
Np->Num->zero_end - Np->out_pre_spaces);
5711+
last_zero = Np->number + last_zero_pos;
57055712
if (Np->last_relevant < last_zero)
57065713
Np->last_relevant = last_zero;
57075714
}

src/test/regress/expected/numeric.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,12 @@ SELECT to_char('100'::numeric, 'FM999');
19291929
100
19301930
(1 row)
19311931

1932+
SELECT to_char('12345678901'::float8, 'FM9999999999D9999900000000000000000');
1933+
to_char
1934+
-----------------
1935+
##########.####
1936+
(1 row)
1937+
19321938
-- Check parsing of literal text in a format string
19331939
SELECT to_char('100'::numeric, 'foo999');
19341940
to_char

src/test/regress/sql/numeric.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ FROM v;
979979
SELECT to_char('100'::numeric, 'FM999.9');
980980
SELECT to_char('100'::numeric, 'FM999.');
981981
SELECT to_char('100'::numeric, 'FM999');
982+
SELECT to_char('12345678901'::float8, 'FM9999999999D9999900000000000000000');
982983

983984
-- Check parsing of literal text in a format string
984985
SELECT to_char('100'::numeric, 'foo999');

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy