mirror of
https://github.com/postgres/postgres.git
synced 2025-05-17 06:41:24 +03:00
ecpg: Fix out-of-bound read in DecodeDateTime()
It was possible for the code to read out-of-bound data from the "day_tab" table with some crafted input data. Let's treat these as invalid input as the month number is incorrect. A test is added to test this case with a check on the errno returned by the decoding routine. A test close to the new one added in this commit was testing for a failure, but did not look at the errno generated, so let's use this commit to also change it, adding a check on the errno returned by DecodeDateTime(). Like the other test scripts, dt_test should likely be expanded to include more checks based on the errnos generated in these code paths. This is left as future work. This issue exists since 2e6f97560a83, so backpatch all the way down. Reported-by: Pavel Nekrasov Author: Bruce Momjian, Pavel Nekrasov Discussion: https://postgr.es/m/18614-6bbe00117352309e@postgresql.org Backpatch-through: 12
This commit is contained in:
parent
d20194cead
commit
fcafbaadf7
@ -2325,10 +2325,10 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
||||
return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
|
||||
|
||||
/*
|
||||
* check for valid day of month, now that we know for sure the month
|
||||
* and year...
|
||||
* check for valid day of month and month, now that we know for sure
|
||||
* the month and year...
|
||||
*/
|
||||
if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
|
||||
if (tm->tm_mon < 1 || tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
|
||||
return -1;
|
||||
|
||||
/*
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pgtypes_date.h>
|
||||
#include <pgtypes_error.h>
|
||||
#include <pgtypes_timestamp.h>
|
||||
#include <pgtypes_interval.h>
|
||||
|
||||
@ -22,9 +23,11 @@
|
||||
|
||||
|
||||
|
||||
#line 8 "dt_test.pgc"
|
||||
#line 9 "dt_test.pgc"
|
||||
|
||||
|
||||
static void check_errno(void);
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@ -34,19 +37,19 @@ main(void)
|
||||
|
||||
|
||||
|
||||
#line 14 "dt_test.pgc"
|
||||
#line 17 "dt_test.pgc"
|
||||
date date1 ;
|
||||
|
||||
#line 15 "dt_test.pgc"
|
||||
#line 18 "dt_test.pgc"
|
||||
timestamp ts1 ;
|
||||
|
||||
#line 16 "dt_test.pgc"
|
||||
#line 19 "dt_test.pgc"
|
||||
interval * iv1 , iv2 ;
|
||||
|
||||
#line 17 "dt_test.pgc"
|
||||
#line 20 "dt_test.pgc"
|
||||
char * text ;
|
||||
/* exec sql end declare section */
|
||||
#line 18 "dt_test.pgc"
|
||||
#line 21 "dt_test.pgc"
|
||||
|
||||
date date2;
|
||||
int mdy[3] = { 4, 19, 1998 };
|
||||
@ -57,31 +60,31 @@ main(void)
|
||||
|
||||
ECPGdebug(1, stderr);
|
||||
/* exec sql whenever sqlerror do sqlprint ( ) ; */
|
||||
#line 27 "dt_test.pgc"
|
||||
#line 30 "dt_test.pgc"
|
||||
|
||||
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0);
|
||||
#line 28 "dt_test.pgc"
|
||||
#line 31 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 28 "dt_test.pgc"
|
||||
#line 31 "dt_test.pgc"
|
||||
|
||||
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table date_test ( d date , ts timestamp )", ECPGt_EOIT, ECPGt_EORT);
|
||||
#line 29 "dt_test.pgc"
|
||||
#line 32 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 29 "dt_test.pgc"
|
||||
#line 32 "dt_test.pgc"
|
||||
|
||||
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT);
|
||||
#line 30 "dt_test.pgc"
|
||||
#line 33 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 30 "dt_test.pgc"
|
||||
#line 33 "dt_test.pgc"
|
||||
|
||||
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set intervalstyle to postgres_verbose", ECPGt_EOIT, ECPGt_EORT);
|
||||
#line 31 "dt_test.pgc"
|
||||
#line 34 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 31 "dt_test.pgc"
|
||||
#line 34 "dt_test.pgc"
|
||||
|
||||
|
||||
date1 = PGTYPESdate_from_asc(d1, NULL);
|
||||
@ -92,10 +95,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
|
||||
ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),
|
||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
|
||||
#line 36 "dt_test.pgc"
|
||||
#line 39 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 36 "dt_test.pgc"
|
||||
#line 39 "dt_test.pgc"
|
||||
|
||||
|
||||
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select * from date_test where d = $1 ",
|
||||
@ -105,10 +108,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
|
||||
ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),
|
||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
|
||||
#line 38 "dt_test.pgc"
|
||||
#line 41 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 38 "dt_test.pgc"
|
||||
#line 41 "dt_test.pgc"
|
||||
|
||||
|
||||
text = PGTYPESdate_to_asc(date1);
|
||||
@ -263,10 +266,19 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
PGTYPESchar_free(text);
|
||||
|
||||
ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
|
||||
/* failure, check error code */
|
||||
check_errno();
|
||||
text = PGTYPEStimestamp_to_asc(ts1);
|
||||
printf("timestamp_to_asc3: %s\n", text);
|
||||
PGTYPESchar_free(text);
|
||||
|
||||
ts1 = PGTYPEStimestamp_from_asc("AM95000062", NULL);
|
||||
/* failure, check error code */
|
||||
check_errno();
|
||||
text = PGTYPEStimestamp_to_asc(ts1);
|
||||
printf("timestamp_to_asc4: %s\n", text);
|
||||
PGTYPESchar_free(text);
|
||||
|
||||
/* abc-03:10:35-def-02/11/94-gh */
|
||||
/* 12345678901234567890123456789 */
|
||||
|
||||
@ -453,17 +465,35 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
free(out);
|
||||
|
||||
{ ECPGtrans(__LINE__, NULL, "rollback");
|
||||
#line 381 "dt_test.pgc"
|
||||
#line 393 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 381 "dt_test.pgc"
|
||||
#line 393 "dt_test.pgc"
|
||||
|
||||
{ ECPGdisconnect(__LINE__, "CURRENT");
|
||||
#line 382 "dt_test.pgc"
|
||||
#line 394 "dt_test.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||
#line 382 "dt_test.pgc"
|
||||
#line 394 "dt_test.pgc"
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
check_errno(void)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case 0:
|
||||
printf("(no errno set) - ");
|
||||
break;
|
||||
case PGTYPES_TS_BAD_TIMESTAMP:
|
||||
printf("(errno == PGTYPES_TS_BAD_TIMESTAMP) - ");
|
||||
break;
|
||||
default:
|
||||
printf("(unknown errno (%d))\n", errno);
|
||||
printf("(libc: (%s)) ", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,47 +2,47 @@
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 29: query: create table date_test ( d date , ts timestamp ); with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: ecpg_execute on line 32: query: create table date_test ( d date , ts timestamp ); with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 29: using PQexec
|
||||
[NO_PID]: ecpg_execute on line 32: using PQexec
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 29: OK: CREATE TABLE
|
||||
[NO_PID]: ecpg_process_output on line 32: OK: CREATE TABLE
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 30: query: set datestyle to iso; with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: ecpg_execute on line 33: query: set datestyle to iso; with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 30: using PQexec
|
||||
[NO_PID]: ecpg_execute on line 33: using PQexec
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 30: OK: SET
|
||||
[NO_PID]: ecpg_process_output on line 33: OK: SET
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 31: query: set intervalstyle to postgres_verbose; with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: ecpg_execute on line 34: query: set intervalstyle to postgres_verbose; with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 31: using PQexec
|
||||
[NO_PID]: ecpg_execute on line 34: using PQexec
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 31: OK: SET
|
||||
[NO_PID]: ecpg_process_output on line 34: OK: SET
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 36: query: insert into date_test ( d , ts ) values ( $1 , $2 ); with 2 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: ecpg_execute on line 39: query: insert into date_test ( d , ts ) values ( $1 , $2 ); with 2 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 36: using PQexecParams
|
||||
[NO_PID]: ecpg_execute on line 39: using PQexecParams
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_free_params on line 36: parameter 1 = 1966-01-17
|
||||
[NO_PID]: ecpg_free_params on line 39: parameter 1 = 1966-01-17
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_free_params on line 36: parameter 2 = 2000-07-12 17:34:29
|
||||
[NO_PID]: ecpg_free_params on line 39: parameter 2 = 2000-07-12 17:34:29
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 36: OK: INSERT 0 1
|
||||
[NO_PID]: ecpg_process_output on line 39: OK: INSERT 0 1
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 38: query: select * from date_test where d = $1 ; with 1 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: ecpg_execute on line 41: query: select * from date_test where d = $1 ; with 1 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 38: using PQexecParams
|
||||
[NO_PID]: ecpg_execute on line 41: using PQexecParams
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_free_params on line 38: parameter 1 = 1966-01-17
|
||||
[NO_PID]: ecpg_free_params on line 41: parameter 1 = 1966-01-17
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 38: correctly got 1 tuples with 2 fields
|
||||
[NO_PID]: ecpg_process_output on line 41: correctly got 1 tuples with 2 fields
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_get_data on line 38: RESULT: 1966-01-17 offset: -1; array: no
|
||||
[NO_PID]: ecpg_get_data on line 41: RESULT: 1966-01-17 offset: -1; array: no
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_get_data on line 38: RESULT: 2000-07-12 17:34:29 offset: -1; array: no
|
||||
[NO_PID]: ecpg_get_data on line 41: RESULT: 2000-07-12 17:34:29 offset: -1; array: no
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ECPGtrans on line 381: action "rollback"; connection "ecpg1_regression"
|
||||
[NO_PID]: ECPGtrans on line 393: action "rollback"; connection "ecpg1_regression"
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
|
@ -20,7 +20,8 @@ date_defmt_asc10: 1995-12-25
|
||||
date_defmt_asc12: 0095-12-25
|
||||
timestamp_to_asc1: 1996-02-29 00:00:00
|
||||
timestamp_to_asc2: 1994-02-11 03:10:35
|
||||
timestamp_to_asc3: 2000-01-01 00:00:00
|
||||
(errno == PGTYPES_TS_BAD_TIMESTAMP) - timestamp_to_asc3: 2000-01-01 00:00:00
|
||||
(errno == PGTYPES_TS_BAD_TIMESTAMP) - timestamp_to_asc4: 2000-01-01 00:00:00
|
||||
timestamp_fmt_asc: 0: abc-00:00:00-def-01/01/00-ghi%
|
||||
timestamp_defmt_asc(This is a 4/12/80 3-39l12test, This is a %m/%d/%y %H-%Ml%Stest) = 1980-04-12 03:39:12, error: 0
|
||||
timestamp_defmt_asc(Tue Jul 22 17:28:44 +0200 2003, %a %b %d %H:%M:%S %z %Y) = 2003-07-22 15:28:44, error: 0
|
||||
|
@ -2,11 +2,14 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pgtypes_date.h>
|
||||
#include <pgtypes_error.h>
|
||||
#include <pgtypes_timestamp.h>
|
||||
#include <pgtypes_interval.h>
|
||||
|
||||
exec sql include ../regression;
|
||||
|
||||
static void check_errno(void);
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@ -189,10 +192,19 @@ main(void)
|
||||
PGTYPESchar_free(text);
|
||||
|
||||
ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
|
||||
/* failure, check error code */
|
||||
check_errno();
|
||||
text = PGTYPEStimestamp_to_asc(ts1);
|
||||
printf("timestamp_to_asc3: %s\n", text);
|
||||
PGTYPESchar_free(text);
|
||||
|
||||
ts1 = PGTYPEStimestamp_from_asc("AM95000062", NULL);
|
||||
/* failure, check error code */
|
||||
check_errno();
|
||||
text = PGTYPEStimestamp_to_asc(ts1);
|
||||
printf("timestamp_to_asc4: %s\n", text);
|
||||
PGTYPESchar_free(text);
|
||||
|
||||
/* abc-03:10:35-def-02/11/94-gh */
|
||||
/* 12345678901234567890123456789 */
|
||||
|
||||
@ -383,3 +395,21 @@ main(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
check_errno(void)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case 0:
|
||||
printf("(no errno set) - ");
|
||||
break;
|
||||
case PGTYPES_TS_BAD_TIMESTAMP:
|
||||
printf("(errno == PGTYPES_TS_BAD_TIMESTAMP) - ");
|
||||
break;
|
||||
default:
|
||||
printf("(unknown errno (%d))\n", errno);
|
||||
printf("(libc: (%s)) ", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user