Skip to content

Commit fe25269

Browse files
committed
to_char(): prevent writing beyond the allocated buffer
Previously very long localized month and weekday strings could overflow the allocated buffers, causing a server crash. Reported and patch reviewed by Noah Misch. Backpatch to all supported versions. Security: CVE-2015-0241
1 parent b8b5801 commit fe25269

File tree

1 file changed

+125
-14
lines changed

1 file changed

+125
-14
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 125 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
* Maximal length of one node
111111
* ----------
112112
*/
113-
#define DCH_MAX_ITEM_SIZ 9 /* max julian day */
113+
#define DCH_MAX_ITEM_SIZ 12 /* max localized day name */
114114
#define NUM_MAX_ITEM_SIZ 8 /* roman number (RN has 15 chars) */
115115

116116
/* ----------
@@ -525,10 +525,12 @@ do { \
525525
* Suffixes definition for DATE-TIME TO/FROM CHAR
526526
* ----------
527527
*/
528+
#define TM_SUFFIX_LEN 2
529+
528530
static KeySuffix DCH_suff[] = {
529531
{"FM", 2, DCH_S_FM, SUFFTYPE_PREFIX},
530532
{"fm", 2, DCH_S_FM, SUFFTYPE_PREFIX},
531-
{"TM", 2, DCH_S_TM, SUFFTYPE_PREFIX},
533+
{"TM", TM_SUFFIX_LEN, DCH_S_TM, SUFFTYPE_PREFIX},
532534
{"tm", 2, DCH_S_TM, SUFFTYPE_PREFIX},
533535
{"TH", 2, DCH_S_TH, SUFFTYPE_POSTFIX},
534536
{"th", 2, DCH_S_th, SUFFTYPE_POSTFIX},
@@ -537,6 +539,7 @@ static KeySuffix DCH_suff[] = {
537539
{NULL, 0, 0, 0}
538540
};
539541

542+
540543
/* ----------
541544
* Format-pictures (KeyWord).
542545
*
@@ -2532,7 +2535,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25322535
if (!tm->tm_mon)
25332536
break;
25342537
if (S_TM(n->suffix))
2535-
strcpy(s, str_toupper_z(localized_full_months[tm->tm_mon - 1], collid));
2538+
{
2539+
char *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
2540+
2541+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2542+
strcpy(s, str);
2543+
else
2544+
ereport(ERROR,
2545+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2546+
errmsg("localized string format value too long")));
2547+
}
25362548
else
25372549
sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
25382550
asc_toupper_z(months_full[tm->tm_mon - 1]));
@@ -2543,7 +2555,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25432555
if (!tm->tm_mon)
25442556
break;
25452557
if (S_TM(n->suffix))
2546-
strcpy(s, str_initcap_z(localized_full_months[tm->tm_mon - 1], collid));
2558+
{
2559+
char *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
2560+
2561+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2562+
strcpy(s, str);
2563+
else
2564+
ereport(ERROR,
2565+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2566+
errmsg("localized string format value too long")));
2567+
}
25472568
else
25482569
sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
25492570
months_full[tm->tm_mon - 1]);
@@ -2554,7 +2575,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25542575
if (!tm->tm_mon)
25552576
break;
25562577
if (S_TM(n->suffix))
2557-
strcpy(s, str_tolower_z(localized_full_months[tm->tm_mon - 1], collid));
2578+
{
2579+
char *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
2580+
2581+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2582+
strcpy(s, str);
2583+
else
2584+
ereport(ERROR,
2585+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2586+
errmsg("localized string format value too long")));
2587+
}
25582588
else
25592589
sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
25602590
asc_tolower_z(months_full[tm->tm_mon - 1]));
@@ -2565,7 +2595,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25652595
if (!tm->tm_mon)
25662596
break;
25672597
if (S_TM(n->suffix))
2568-
strcpy(s, str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid));
2598+
{
2599+
char *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2600+
2601+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2602+
strcpy(s, str);
2603+
else
2604+
ereport(ERROR,
2605+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2606+
errmsg("localized string format value too long")));
2607+
}
25692608
else
25702609
strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
25712610
s += strlen(s);
@@ -2575,7 +2614,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25752614
if (!tm->tm_mon)
25762615
break;
25772616
if (S_TM(n->suffix))
2578-
strcpy(s, str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid));
2617+
{
2618+
char *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2619+
2620+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2621+
strcpy(s, str);
2622+
else
2623+
ereport(ERROR,
2624+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2625+
errmsg("localized string format value too long")));
2626+
}
25792627
else
25802628
strcpy(s, months[tm->tm_mon - 1]);
25812629
s += strlen(s);
@@ -2585,7 +2633,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25852633
if (!tm->tm_mon)
25862634
break;
25872635
if (S_TM(n->suffix))
2588-
strcpy(s, str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid));
2636+
{
2637+
char *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2638+
2639+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2640+
strcpy(s, str);
2641+
else
2642+
ereport(ERROR,
2643+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2644+
errmsg("localized string format value too long")));
2645+
}
25892646
else
25902647
strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
25912648
s += strlen(s);
@@ -2599,7 +2656,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
25992656
case DCH_DAY:
26002657
INVALID_FOR_INTERVAL;
26012658
if (S_TM(n->suffix))
2602-
strcpy(s, str_toupper_z(localized_full_days[tm->tm_wday], collid));
2659+
{
2660+
char *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
2661+
2662+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2663+
strcpy(s, str);
2664+
else
2665+
ereport(ERROR,
2666+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2667+
errmsg("localized string format value too long")));
2668+
}
26032669
else
26042670
sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
26052671
asc_toupper_z(days[tm->tm_wday]));
@@ -2608,7 +2674,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
26082674
case DCH_Day:
26092675
INVALID_FOR_INTERVAL;
26102676
if (S_TM(n->suffix))
2611-
strcpy(s, str_initcap_z(localized_full_days[tm->tm_wday], collid));
2677+
{
2678+
char *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
2679+
2680+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2681+
strcpy(s, str);
2682+
else
2683+
ereport(ERROR,
2684+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2685+
errmsg("localized string format value too long")));
2686+
}
26122687
else
26132688
sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
26142689
days[tm->tm_wday]);
@@ -2617,7 +2692,16 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
26172692
case DCH_day:
26182693
INVALID_FOR_INTERVAL;
26192694
if (S_TM(n->suffix))
2620-
strcpy(s, str_tolower_z(localized_full_days[tm->tm_wday], collid));
2695+
{
2696+
char *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
2697+
2698+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2699+
strcpy(s, str);
2700+
else
2701+
ereport(ERROR,
2702+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2703+
errmsg("localized string format value too long")));
2704+
}
26212705
else
26222706
sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
26232707
asc_tolower_z(days[tm->tm_wday]));
@@ -2626,23 +2710,50 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
26262710
case DCH_DY:
26272711
INVALID_FOR_INTERVAL;
26282712
if (S_TM(n->suffix))
2629-
strcpy(s, str_toupper_z(localized_abbrev_days[tm->tm_wday], collid));
2713+
{
2714+
char *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
2715+
2716+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2717+
strcpy(s, str);
2718+
else
2719+
ereport(ERROR,
2720+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2721+
errmsg("localized string format value too long")));
2722+
}
26302723
else
26312724
strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
26322725
s += strlen(s);
26332726
break;
26342727
case DCH_Dy:
26352728
INVALID_FOR_INTERVAL;
26362729
if (S_TM(n->suffix))
2637-
strcpy(s, str_initcap_z(localized_abbrev_days[tm->tm_wday], collid));
2730+
{
2731+
char *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
2732+
2733+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2734+
strcpy(s, str);
2735+
else
2736+
ereport(ERROR,
2737+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2738+
errmsg("localized string format value too long")));
2739+
}
26382740
else
26392741
strcpy(s, days_short[tm->tm_wday]);
26402742
s += strlen(s);
26412743
break;
26422744
case DCH_dy:
26432745
INVALID_FOR_INTERVAL;
26442746
if (S_TM(n->suffix))
2645-
strcpy(s, str_tolower_z(localized_abbrev_days[tm->tm_wday], collid));
2747+
{
2748+
char *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
2749+
2750+
if (strlen(str) < (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2751+
strcpy(s, str);
2752+
else
2753+
ereport(ERROR,
2754+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2755+
errmsg("localized string format value too long")));
2756+
}
26462757
else
26472758
strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
26482759
s += strlen(s);

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