mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +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 2e6f97560a
, 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:
src/interfaces/ecpg
pgtypeslib
test
@ -2325,10 +2325,10 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
|
return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check for valid day of month, now that we know for sure the month
|
* check for valid day of month and month, now that we know for sure
|
||||||
* and year...
|
* 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;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pgtypes_date.h>
|
#include <pgtypes_date.h>
|
||||||
|
#include <pgtypes_error.h>
|
||||||
#include <pgtypes_timestamp.h>
|
#include <pgtypes_timestamp.h>
|
||||||
#include <pgtypes_interval.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
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
@ -34,19 +37,19 @@ main(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#line 14 "dt_test.pgc"
|
#line 17 "dt_test.pgc"
|
||||||
date date1 ;
|
date date1 ;
|
||||||
|
|
||||||
#line 15 "dt_test.pgc"
|
#line 18 "dt_test.pgc"
|
||||||
timestamp ts1 ;
|
timestamp ts1 ;
|
||||||
|
|
||||||
#line 16 "dt_test.pgc"
|
#line 19 "dt_test.pgc"
|
||||||
interval * iv1 , iv2 ;
|
interval * iv1 , iv2 ;
|
||||||
|
|
||||||
#line 17 "dt_test.pgc"
|
#line 20 "dt_test.pgc"
|
||||||
char * text ;
|
char * text ;
|
||||||
/* exec sql end declare section */
|
/* exec sql end declare section */
|
||||||
#line 18 "dt_test.pgc"
|
#line 21 "dt_test.pgc"
|
||||||
|
|
||||||
date date2;
|
date date2;
|
||||||
int mdy[3] = { 4, 19, 1998 };
|
int mdy[3] = { 4, 19, 1998 };
|
||||||
@ -57,31 +60,31 @@ main(void)
|
|||||||
|
|
||||||
ECPGdebug(1, stderr);
|
ECPGdebug(1, stderr);
|
||||||
/* exec sql whenever sqlerror do sqlprint ( ) ; */
|
/* 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);
|
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0);
|
||||||
#line 28 "dt_test.pgc"
|
#line 31 "dt_test.pgc"
|
||||||
|
|
||||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
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);
|
{ 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 ( );}
|
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);
|
{ 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 ( );}
|
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);
|
{ 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 ( );}
|
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||||
#line 31 "dt_test.pgc"
|
#line 34 "dt_test.pgc"
|
||||||
|
|
||||||
|
|
||||||
date1 = PGTYPESdate_from_asc(d1, NULL);
|
date1 = PGTYPESdate_from_asc(d1, NULL);
|
||||||
@ -92,10 +95,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
|||||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
|
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
|
||||||
ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),
|
ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),
|
||||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
|
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 ( );}
|
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 ",
|
{ 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_NO_INDICATOR, NULL , 0L, 0L, 0L,
|
||||||
ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),
|
ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),
|
||||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
|
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
|
||||||
#line 38 "dt_test.pgc"
|
#line 41 "dt_test.pgc"
|
||||||
|
|
||||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||||
#line 38 "dt_test.pgc"
|
#line 41 "dt_test.pgc"
|
||||||
|
|
||||||
|
|
||||||
text = PGTYPESdate_to_asc(date1);
|
text = PGTYPESdate_to_asc(date1);
|
||||||
@ -263,10 +266,19 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
|||||||
PGTYPESchar_free(text);
|
PGTYPESchar_free(text);
|
||||||
|
|
||||||
ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
|
ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
|
||||||
|
/* failure, check error code */
|
||||||
|
check_errno();
|
||||||
text = PGTYPEStimestamp_to_asc(ts1);
|
text = PGTYPEStimestamp_to_asc(ts1);
|
||||||
printf("timestamp_to_asc3: %s\n", text);
|
printf("timestamp_to_asc3: %s\n", text);
|
||||||
PGTYPESchar_free(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 */
|
/* abc-03:10:35-def-02/11/94-gh */
|
||||||
/* 12345678901234567890123456789 */
|
/* 12345678901234567890123456789 */
|
||||||
|
|
||||||
@ -453,17 +465,35 @@ if (sqlca.sqlcode < 0) sqlprint ( );}
|
|||||||
free(out);
|
free(out);
|
||||||
|
|
||||||
{ ECPGtrans(__LINE__, NULL, "rollback");
|
{ ECPGtrans(__LINE__, NULL, "rollback");
|
||||||
#line 381 "dt_test.pgc"
|
#line 393 "dt_test.pgc"
|
||||||
|
|
||||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||||
#line 381 "dt_test.pgc"
|
#line 393 "dt_test.pgc"
|
||||||
|
|
||||||
{ ECPGdisconnect(__LINE__, "CURRENT");
|
{ ECPGdisconnect(__LINE__, "CURRENT");
|
||||||
#line 382 "dt_test.pgc"
|
#line 394 "dt_test.pgc"
|
||||||
|
|
||||||
if (sqlca.sqlcode < 0) sqlprint ( );}
|
if (sqlca.sqlcode < 0) sqlprint ( );}
|
||||||
#line 382 "dt_test.pgc"
|
#line 394 "dt_test.pgc"
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
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]: sqlca: code: 0, state: 00000
|
||||||
[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>
|
[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>
|
||||||
[NO_PID]: sqlca: code: 0, state: 00000
|
[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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: 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]: sqlca: code: 0, state: 00000
|
||||||
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
|
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
|
||||||
[NO_PID]: sqlca: code: 0, state: 00000
|
[NO_PID]: sqlca: code: 0, state: 00000
|
||||||
|
@ -20,7 +20,8 @@ date_defmt_asc10: 1995-12-25
|
|||||||
date_defmt_asc12: 0095-12-25
|
date_defmt_asc12: 0095-12-25
|
||||||
timestamp_to_asc1: 1996-02-29 00:00:00
|
timestamp_to_asc1: 1996-02-29 00:00:00
|
||||||
timestamp_to_asc2: 1994-02-11 03:10:35
|
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_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(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
|
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 <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pgtypes_date.h>
|
#include <pgtypes_date.h>
|
||||||
|
#include <pgtypes_error.h>
|
||||||
#include <pgtypes_timestamp.h>
|
#include <pgtypes_timestamp.h>
|
||||||
#include <pgtypes_interval.h>
|
#include <pgtypes_interval.h>
|
||||||
|
|
||||||
exec sql include ../regression;
|
exec sql include ../regression;
|
||||||
|
|
||||||
|
static void check_errno(void);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
@ -189,10 +192,19 @@ main(void)
|
|||||||
PGTYPESchar_free(text);
|
PGTYPESchar_free(text);
|
||||||
|
|
||||||
ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
|
ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL);
|
||||||
|
/* failure, check error code */
|
||||||
|
check_errno();
|
||||||
text = PGTYPEStimestamp_to_asc(ts1);
|
text = PGTYPEStimestamp_to_asc(ts1);
|
||||||
printf("timestamp_to_asc3: %s\n", text);
|
printf("timestamp_to_asc3: %s\n", text);
|
||||||
PGTYPESchar_free(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 */
|
/* abc-03:10:35-def-02/11/94-gh */
|
||||||
/* 12345678901234567890123456789 */
|
/* 12345678901234567890123456789 */
|
||||||
|
|
||||||
@ -383,3 +395,21 @@ main(void)
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user