Skip to content

Commit 3ff660b

Browse files
committed
Fix off-by-one error in PGTYPEStimestamp_fmt_asc
When using %b or %B patterns to format a date, the code was simply using tm_mon as an index into array of month names. But that is wrong, because tm_mon is 1-based, while array indexes are 0-based. The result is we either use name of the next month, or a segfault (for December). Fix by subtracting 1 from tm_mon for both patterns, and add a regression test triggering the issue. Backpatch to all supported versions (the bug is there far longer, since at least 2003). Reported-by: Paul Spencer Backpatch-through: 9.4 Discussion: https://postgr.es/m/16143-0d861eb8688d3fef%40postgresql.org
1 parent 98a9b37 commit 3ff660b

File tree

5 files changed

+41
-7
lines changed

5 files changed

+41
-7
lines changed

src/interfaces/ecpg/pgtypeslib/timestamp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,13 @@ dttofmtasc_replace(timestamp * ts, date dDate, int dow, struct tm *tm,
334334
/* XXX should be locale aware */
335335
case 'b':
336336
case 'h':
337-
replace_val.str_val = months[tm->tm_mon];
337+
replace_val.str_val = months[tm->tm_mon - 1];
338338
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
339339
break;
340340
/* the full name of the month */
341341
/* XXX should be locale aware */
342342
case 'B':
343-
replace_val.str_val = pgtypes_date_months[tm->tm_mon];
343+
replace_val.str_val = pgtypes_date_months[tm->tm_mon - 1];
344344
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
345345
break;
346346

src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,17 +436,33 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
436436
printf("timestamp_defmt_asc(%s, %s) = %s, error: %d\n", in, fmt, text, i);
437437
PGTYPESchar_free(text);
438438

439+
out = (char*) malloc(64);
440+
fmt = "%a %b %d %H:%M:%S %Y";
441+
in = "Mon Dec 30 17:28:44 2019";
442+
i = PGTYPEStimestamp_defmt_asc(in, fmt, &ts1);
443+
i = PGTYPEStimestamp_fmt_asc(&ts1, out, 63, fmt);
444+
printf("timestamp_defmt_asc(%s, %s) = %s, error: %d\n", in, fmt, out, i);
445+
free(out);
446+
447+
out = (char*) malloc(64);
448+
fmt = "%a %b %d %H:%M:%S %Y";
449+
in = "Mon December 30 17:28:44 2019";
450+
i = PGTYPEStimestamp_defmt_asc(in, fmt, &ts1);
451+
i = PGTYPEStimestamp_fmt_asc(&ts1, out, 63, fmt);
452+
printf("timestamp_defmt_asc(%s, %s) = %s, error: %d\n", in, fmt, out, i);
453+
free(out);
454+
439455
{ ECPGtrans(__LINE__, NULL, "rollback");
440-
#line 365 "dt_test.pgc"
456+
#line 381 "dt_test.pgc"
441457

442458
if (sqlca.sqlcode < 0) sqlprint ( );}
443-
#line 365 "dt_test.pgc"
459+
#line 381 "dt_test.pgc"
444460

445461
{ ECPGdisconnect(__LINE__, "CURRENT");
446-
#line 366 "dt_test.pgc"
462+
#line 382 "dt_test.pgc"
447463

448464
if (sqlca.sqlcode < 0) sqlprint ( );}
449-
#line 366 "dt_test.pgc"
465+
#line 382 "dt_test.pgc"
450466

451467

452468
return 0;

src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
[NO_PID]: sqlca: code: 0, state: 00000
4343
[NO_PID]: ecpg_get_data on line 38: RESULT: 2000-07-12 17:34:29 offset: -1; array: no
4444
[NO_PID]: sqlca: code: 0, state: 00000
45-
[NO_PID]: ECPGtrans on line 365: action "rollback"; connection "ecpg1_regression"
45+
[NO_PID]: ECPGtrans on line 381: action "rollback"; connection "ecpg1_regression"
4646
[NO_PID]: sqlca: code: 0, state: 00000
4747
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
4848
[NO_PID]: sqlca: code: 0, state: 00000

src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,5 @@ timestamp_defmt_asc( 1976, July 14. Time: 9:15am, %Y, %B %d. Time: %I:%M %p)
4848
timestamp_defmt_asc( 1976, July 14. Time: 9:15 am, %Y, %B %d. Time: %I:%M%p) = 1976-07-14 09:15:00, error: 0
4949
timestamp_defmt_asc( 1976, P.M. July 14. Time: 9:15, %Y, %P %B %d. Time: %I:%M) = 1976-07-14 21:15:00, error: 0
5050
timestamp_defmt_asc(1234567890, %s) = 2009-02-13 23:31:30, error: 0
51+
timestamp_defmt_asc(Mon Dec 30 17:28:44 2019, %a %b %d %H:%M:%S %Y) = Mon Dec 30 17:28:44 2019, error: 0
52+
timestamp_defmt_asc(Mon December 30 17:28:44 2019, %a %b %d %H:%M:%S %Y) = Mon Dec 30 17:28:44 2019, error: 0

src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,22 @@ main(void)
362362
printf("timestamp_defmt_asc(%s, %s) = %s, error: %d\n", in, fmt, text, i);
363363
PGTYPESchar_free(text);
364364

365+
out = (char*) malloc(64);
366+
fmt = "%a %b %d %H:%M:%S %Y";
367+
in = "Mon Dec 30 17:28:44 2019";
368+
i = PGTYPEStimestamp_defmt_asc(in, fmt, &ts1);
369+
i = PGTYPEStimestamp_fmt_asc(&ts1, out, 63, fmt);
370+
printf("timestamp_defmt_asc(%s, %s) = %s, error: %d\n", in, fmt, out, i);
371+
free(out);
372+
373+
out = (char*) malloc(64);
374+
fmt = "%a %b %d %H:%M:%S %Y";
375+
in = "Mon December 30 17:28:44 2019";
376+
i = PGTYPEStimestamp_defmt_asc(in, fmt, &ts1);
377+
i = PGTYPEStimestamp_fmt_asc(&ts1, out, 63, fmt);
378+
printf("timestamp_defmt_asc(%s, %s) = %s, error: %d\n", in, fmt, out, i);
379+
free(out);
380+
365381
exec sql rollback;
366382
exec sql disconnect;
367383

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