Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1t37qS-00AZBP-RR for pgsql-bugs@arkaria.postgresql.org; Tue, 22 Oct 2024 05:54:17 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1t37qO-00EZfA-O6 for pgsql-bugs@arkaria.postgresql.org; Tue, 22 Oct 2024 05:54:13 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1t37qO-00EZf1-CE for pgsql-bugs@lists.postgresql.org; Tue, 22 Oct 2024 05:54:12 +0000 Received: from fout-a5-smtp.messagingengine.com ([103.168.172.148]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1t37qL-002L8a-ML for pgsql-bugs@lists.postgresql.org; Tue, 22 Oct 2024 05:54:11 +0000 Received: from phl-compute-08.internal (phl-compute-08.phl.internal [10.202.2.48]) by mailfout.phl.internal (Postfix) with ESMTP id 4B54D1380260; Tue, 22 Oct 2024 01:54:08 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-08.internal (MEProxy); Tue, 22 Oct 2024 01:54:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paquier.xyz; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm3; t=1729576448; x=1729662848; bh=z5FWK7IsYm OlUkzJYSAoUwQ6qmfK1jv9MKi0UhBTsi8=; b=jSrA0nFASIi3DQQNWRAarr63vU TsPpW0WukoAWloacPDrwwQkyHJsUAmuEPjVP2Cdu3KM8txDXvaq2FTvrNk9VlxDA rjStLj7xKRpJ1MborspSWdRkDJHGpVeWgDZWyYBhOMP2NTb1vdSMef+zyJ6SxGg4 U5P+x+RiTcAZrXRaM/1zkRm2ht1a1DRxSlPTyPzX6aFWDPu3JAXmqtPugn8TdPgR cMCI1hkQB6uzQeKGgJj4KB5ri31UopwUHoTK3/+0hg+N5PouP2EKmtoFQzP5p/y2 /Iin7/teaGdpEIxqhV08K3PWiGY2ml5GGSXeHz2WapQNnDsRj1jEt5idhyVw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1729576448; x=1729662848; bh=z5FWK7IsYmOlUkzJYSAoUwQ6qmfK 1jv9MKi0UhBTsi8=; b=iROBG7eAYcxZ1gA/kzylXqII3TfiOFVpwFeGp8kSwr87 DQEKqs2IFK/mHzX4lXKUs9rFEj9MlDsPOv2+KGCvpq6EZHUd+qc/pKCJ8+Xdru4Y Z4ou/hw9cwnNc04qEFVZJsOprEQcbvMxfo602TXGBU1MyzZArwuVTRf7YFKNKQkJ FAi/rkDiPyorxD2cZvBHr8SEusPS/f/n+yGDYUSAGYEVDavvzTGSd/hAg76X0836 YQ7Kz+Pv329WOU6arNUt486I+vwZadJUsWPhqrKlxDmR2L03cs1UFGtU5PK7Nray Xpg5QN4lYdYuW2hiHxob+p43iTQqKeVAi4/7Q/hzoQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrvdeifedgvddvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnh htshculddquddttddmnegfrhhlucfvnfffucdljedtmdenucfjughrpeffhffvvefukfhf gggtuggjsehgtderredttddvnecuhfhrohhmpefoihgthhgrvghlucfrrghquhhivghruc eomhhitghhrggvlhesphgrqhhuihgvrhdrgiihiieqnecuggftrfgrthhtvghrnhepteel ieefudffhffhtdetleeggeegfffhkeeuveetiefgudduvedutefggeeivdejnecuvehluh hsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepmhhitghhrggvlhes phgrqhhuihgvrhdrgiihiidpnhgspghrtghpthhtohepfedpmhhouggvpehsmhhtphhouh htpdhrtghpthhtohepsghruhgtvgesmhhomhhjihgrnhdruhhspdhrtghpthhtohepphdr nhgvkhhrrghsohhvsehfohgsohhsqdhnthdrrhhupdhrtghpthhtohepphhgshhqlhdqsg hughhssehlihhsthhsrdhpohhsthhgrhgvshhqlhdrohhrgh X-ME-Proxy: Feedback-ID: i0fe9450f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 22 Oct 2024 01:54:06 -0400 (EDT) Date: Tue, 22 Oct 2024 14:53:50 +0900 From: Michael Paquier To: Bruce Momjian Cc: p.nekrasov@fobos-nt.ru, pgsql-bugs@lists.postgresql.org Subject: Re: BUG #18614: [ECPG] out of bound in DecodeDateTime Message-ID: References: <18614-6bbe00117352309e@postgresql.org> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="YpmmVocpHY51BRM/" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --YpmmVocpHY51BRM/ Content-Type: multipart/mixed; boundary="xJ29oEKu0RISocI3" Content-Disposition: inline --xJ29oEKu0RISocI3 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Oct 18, 2024 at 02:51:32PM +0900, Michael Paquier wrote: > It is not entirely the fault of this patch, because the same error is > done a couple of lines above when using an incorrect hour number with > timestamp_to_asc3. The correct thing to do would be in the lines of > what num_test2.pgc does with its check_errno(), I think where we'd > check for the errno returned by PGTYPEStimestamp_from_asc() and > printf() its information in the output of the test. And we should do > that for both the old timestamp_to_asc3 and your new timestamp_to_asc4 > if we want to be completely correct. And here is what I had in mind, checking the error code on top of the output. The output is really optional, but that maps with 0 with the offset applied, so I've just kept it. -- Michael --xJ29oEKu0RISocI3 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-ecpg-Fix-out-of-bound-read-in-DecodeDateTime.patch" Content-Transfer-Encoding: quoted-printable =46rom 97fd8f946e76a3bbe878bab4dfce8f64adfe35c6 Mon Sep 17 00:00:00 2001 =46rom: Michael Paquier Date: Tue, 22 Oct 2024 14:52:11 +0900 Subject: [PATCH] ecpg: Fix out-of-bound read in DecodeDateTime() blah. Backpatch-through: 12 --- src/interfaces/ecpg/pgtypeslib/dt_common.c | 6 +- .../ecpg/test/expected/pgtypeslib-dt_test.c | 76 +++++++++++++------ .../test/expected/pgtypeslib-dt_test.stderr | 42 +++++----- .../test/expected/pgtypeslib-dt_test.stdout | 3 +- .../ecpg/test/pgtypeslib/dt_test.pgc | 30 ++++++++ 5 files changed, 109 insertions(+), 48 deletions(-) diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ec= pg/pgtypeslib/dt_common.c index 0d63fe52c5..c4119ab793 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt_common.c +++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c @@ -2327,10 +2327,10 @@ DecodeDateTime(char **field, int *ftype, int nf, return ((fmask & DTK_TIME_M) =3D=3D DTK_TIME_M) ? 1 : -1; =20 /* - * 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; =20 /* diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c b/src/i= nterfaces/ecpg/test/expected/pgtypeslib-dt_test.c index ee867b6dd8..ae27b0d433 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include =20 @@ -22,9 +23,11 @@ =20 =20 =20 -#line 8 "dt_test.pgc" +#line 9 "dt_test.pgc" =20 =20 +static void check_errno(void); + int main(void) { @@ -34,19 +37,19 @@ main(void) =20 =20 =09 -#line 14 "dt_test.pgc" +#line 17 "dt_test.pgc" date date1 ; =20 -#line 15 "dt_test.pgc" +#line 18 "dt_test.pgc" timestamp ts1 ; =20 -#line 16 "dt_test.pgc" +#line 19 "dt_test.pgc" interval * iv1 , iv2 ; =20 -#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" =20 date date2; int mdy[3] =3D { 4, 19, 1998 }; @@ -57,31 +60,31 @@ main(void) =20 ECPGdebug(1, stderr); /* exec sql whenever sqlerror do sqlprint ( ) ; */ -#line 27 "dt_test.pgc" +#line 30 "dt_test.pgc" =20 { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0);=20 -#line 28 "dt_test.pgc" +#line 31 "dt_test.pgc" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 28 "dt_test.pgc" +#line 31 "dt_test.pgc" =20 { 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" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 29 "dt_test.pgc" +#line 32 "dt_test.pgc" =20 { 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" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 30 "dt_test.pgc" +#line 33 "dt_test.pgc" =20 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set intervalstyle to po= stgres_verbose", ECPGt_EOIT, ECPGt_EORT); -#line 31 "dt_test.pgc" +#line 34 "dt_test.pgc" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 31 "dt_test.pgc" +#line 34 "dt_test.pgc" =20 =20 date1 =3D PGTYPESdate_from_asc(d1, NULL); @@ -92,10 +95,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,=20 ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),=20 ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); -#line 36 "dt_test.pgc" +#line 39 "dt_test.pgc" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 36 "dt_test.pgc" +#line 39 "dt_test.pgc" =20 =20 { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select * from date_test= where d =3D $1 ",=20 @@ -105,10 +108,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,=20 ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp),=20 ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 38 "dt_test.pgc" +#line 41 "dt_test.pgc" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 38 "dt_test.pgc" +#line 41 "dt_test.pgc" =20 =20 text =3D PGTYPESdate_to_asc(date1); @@ -263,10 +266,19 @@ if (sqlca.sqlcode < 0) sqlprint ( );} PGTYPESchar_free(text); =20 ts1 =3D PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL); + /* failure, check error code */ + check_errno(); text =3D PGTYPEStimestamp_to_asc(ts1); printf("timestamp_to_asc3: %s\n", text); PGTYPESchar_free(text); =20 + ts1 =3D PGTYPEStimestamp_from_asc("AM95000062", NULL); + /* failure, check error code */ + check_errno(); + text =3D PGTYPEStimestamp_to_asc(ts1); + printf("timestamp_to_asc4: %s\n", text); + PGTYPESchar_free(text); + /* abc-03:10:35-def-02/11/94-gh */ /* 12345678901234567890123456789 */ =20 @@ -453,17 +465,35 @@ if (sqlca.sqlcode < 0) sqlprint ( );} free(out); =20 { ECPGtrans(__LINE__, NULL, "rollback"); -#line 381 "dt_test.pgc" +#line 393 "dt_test.pgc" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 381 "dt_test.pgc" +#line 393 "dt_test.pgc" =20 { ECPGdisconnect(__LINE__, "CURRENT"); -#line 382 "dt_test.pgc" +#line 394 "dt_test.pgc" =20 if (sqlca.sqlcode < 0) sqlprint ( );} -#line 382 "dt_test.pgc" +#line 394 "dt_test.pgc" =20 =20 return 0; } + +static void +check_errno(void) +{ + switch(errno) + { + case 0: + printf("(no errno set) - "); + break; + case PGTYPES_TS_BAD_TIMESTAMP: + printf("(errno =3D=3D PGTYPES_TS_BAD_TIMESTAMP) - "); + break; + default: + printf("(unknown errno (%d))\n", errno); + printf("(libc: (%s)) ", strerror(errno)); + break; + } +} diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr b/= src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr index 6e9ed3d3db..2a109ee7fa 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr @@ -2,47 +2,47 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGconnect: opening database ecpg1_regression on port= =20 [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 par= ameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 33: query: set datestyle to iso; with 0 par= ameter(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_ve= rbose; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 34: query: set intervalstyle to postgres_ve= rbose; 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 =3D 1966-01-17 +[NO_PID]: ecpg_free_params on line 39: parameter 1 =3D 1966-01-17 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_free_params on line 36: parameter 2 =3D 2000-07-12 17:34:29 +[NO_PID]: ecpg_free_params on line 39: parameter 2 =3D 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 = =3D $1 ; with 1 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 41: query: select * from date_test where d = =3D $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 =3D 1966-01-17 +[NO_PID]: ecpg_free_params on line 41: parameter 1 =3D 1966-01-17 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 38: correctly got 1 tuples with 2 fi= elds +[NO_PID]: ecpg_process_output on line 41: correctly got 1 tuples with 2 fi= elds [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_regr= ession" +[NO_PID]: ECPGtrans on line 393: action "rollback"; connection "ecpg1_regr= ession" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection ecpg1_regression closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout b/= src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout index 4b582fd7a2..6b8bcc9fc2 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout @@ -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 =3D=3D PGTYPES_TS_BAD_TIMESTAMP) - timestamp_to_asc3: 2000-01-01 00= :00:00 +(errno =3D=3D 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) =3D 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) =3D 2003-07-22 15:28:44, error: 0 diff --git a/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc b/src/interfac= es/ecpg/test/pgtypeslib/dt_test.pgc index f81a392665..b34e1d2f06 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc +++ b/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc @@ -2,11 +2,14 @@ #include #include #include +#include #include #include =20 exec sql include ../regression; =20 +static void check_errno(void); + int main(void) { @@ -189,10 +192,19 @@ main(void) PGTYPESchar_free(text); =20 ts1 =3D PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL); + /* failure, check error code */ + check_errno(); text =3D PGTYPEStimestamp_to_asc(ts1); printf("timestamp_to_asc3: %s\n", text); PGTYPESchar_free(text); =20 + ts1 =3D PGTYPEStimestamp_from_asc("AM95000062", NULL); + /* failure, check error code */ + check_errno(); + text =3D PGTYPEStimestamp_to_asc(ts1); + printf("timestamp_to_asc4: %s\n", text); + PGTYPESchar_free(text); + /* abc-03:10:35-def-02/11/94-gh */ /* 12345678901234567890123456789 */ =20 @@ -383,3 +395,21 @@ main(void) =20 return 0; } + +static void +check_errno(void) +{ + switch(errno) + { + case 0: + printf("(no errno set) - "); + break; + case PGTYPES_TS_BAD_TIMESTAMP: + printf("(errno =3D=3D PGTYPES_TS_BAD_TIMESTAMP) - "); + break; + default: + printf("(unknown errno (%d))\n", errno); + printf("(libc: (%s)) ", strerror(errno)); + break; + } +} --=20 2.45.2 --xJ29oEKu0RISocI3-- --YpmmVocpHY51BRM/ Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEG72nH6vTowiyblFKnvQgOdbyQH0FAmcXPe4ACgkQnvQgOdby QH15yw/+M4p5VYTxEACKgrSr9GWVfrpYBz+W6C8YWYUNb/9oaWHQMMoeawWnFKH/ IUXkwiPd4agiADtACcKMp0vh0AnxuQXVgSza/SnQTST3Dr34mJjk9RPPcmjsm+Ph 8j/AQ7I6Pe/x25f/JjO+R9sj8+ZgaYnaOBlncQD/py/Ere7IE/YHeWY2Ur0dgJXS GTYY4RhmUECB+QCJRXPw0tFLLwNodMIoXDXKdNP4J7nNxJU3dEYIHj9i1lxdsUfh JMJbAQvRnzhvdO31jX0CkWFOH+g5rPbIqXHZMd3JZeP5SynM88zFUrxr0YZl803f ThzZcGBeLfyBObzV2RME/Pglg+F0ptbvBUZmoNUEXKtNdHdfdyiNcbBJvVlJlaOr Nl68sBYU8WxrRoarR0P3upqL6KiRQ1uH4Prhp1FyWYH5pWOv2bRIM4WwVb7VwZvN 4Bw33kBixfD3PBJT6N0LtwHsTj+b4ndy2KCZCXQnWymep24yA0Lj79VXL4nASL3L Kt5Zrbyp4b3LcXOO0cv1kXS0uuoqnBifoe7ANeurYN/TvSTvMF9mgDz6Pa0MGZrs U62X7aGlF3Gev6cgQc1MBGXA/Rwbp8ZnMtdwWSo/SABAu/1MXBkpKRMRYavLViVQ WYmc8Pm/Ufzi0WDG5pTFHQ9QIqc1+D+Sv329i7JwbHTRBcu6Czs= =tIH+ -----END PGP SIGNATURE----- --YpmmVocpHY51BRM/--