From eeb8e68b79e38d925ce7cac6ab2a356df9799bb9 Mon Sep 17 00:00:00 2001 From: Sivirilova Maria Date: Wed, 19 Aug 2026 16:05:32 +0700 Subject: [PATCH] Fix heap-buffer-overflow in PGTYPEStimestamp_defmt_scan() When parsing format tokens '%D', '%r', '%R', or '%T', the function allocated memory for the temporary buffer based on the length of the remaining input string (pstr). However, it subsequently appended the remaining format string (pfmt) to that buffer via strcat(). If the tail of the format string happened to be longer than the remaining input string, a heap-buffer-overflow occurred. Fix this by calculating the required buffer size using the length of the format string (pfmt) instead of the input string (pstr). Author: Maria Sivirilova Co-authored-by: Kanatbek Kanybekov --- src/interfaces/ecpg/pgtypeslib/dt_common.c | 8 ++++---- src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c index f0889dddaf9..6d58dee7890 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt_common.c +++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c @@ -2658,7 +2658,7 @@ PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d, * find the end of the substitution */ pfmt++; - tmp = pgtypes_alloc(strlen("%m/%d/%y") + strlen(pstr) + 1); + tmp = pgtypes_alloc(strlen("%m/%d/%y") + strlen(pfmt) + 1); if (!tmp) return 1; strcpy(tmp, "%m/%d/%y"); @@ -2785,7 +2785,7 @@ PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d, break; case 'r': pfmt++; - tmp = pgtypes_alloc(strlen("%I:%M:%S %p") + strlen(pstr) + 1); + tmp = pgtypes_alloc(strlen("%I:%M:%S %p") + strlen(pfmt) + 1); if (!tmp) return 1; strcpy(tmp, "%I:%M:%S %p"); @@ -2795,7 +2795,7 @@ PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d, return err; case 'R': pfmt++; - tmp = pgtypes_alloc(strlen("%H:%M") + strlen(pstr) + 1); + tmp = pgtypes_alloc(strlen("%H:%M") + strlen(pfmt) + 1); if (!tmp) return 1; strcpy(tmp, "%H:%M"); @@ -2842,7 +2842,7 @@ PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d, break; case 'T': pfmt++; - tmp = pgtypes_alloc(strlen("%H:%M:%S") + strlen(pstr) + 1); + tmp = pgtypes_alloc(strlen("%H:%M:%S") + strlen(pfmt) + 1); if (!tmp) return 1; strcpy(tmp, "%H:%M:%S"); diff --git a/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc b/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc index 62b934b07ee..101fccce6a8 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc +++ b/src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc @@ -66,6 +66,12 @@ main(void) date *dc; exec sql end declare section; + char large_fmt[10000] = { + [0] = '%', + [1] = 'D', + [2 ... 9998] = 'A' + }; + int i, j; char *endptr; @@ -147,5 +153,8 @@ main(void) PGTYPESinterval_free(i1); } + PGTYPEStimestamp_defmt_asc("1 minute", large_fmt, &ts1); + printf("Success parsing large string\n"); + return 0; } -- 2.43.0