ecpg: Fix zero-termination of string generated by intoasc()

intoasc(), a wrapper for PGTYPESinterval_to_asc that converts an
interval to its textual representation, used a plain memcpy() when
copying its result.  This could miss a zero-termination in the result
string, leading to an incorrect result.

The routines in informix.c do not provide the length of their result
buffer, which would allow a replacement of strcpy() to safer strlcpy()
calls, but this requires an ABI breakage and that cannot happen in
back-branches.

Author: Oleg Tselebrovskiy
Reviewed-by: Ashutosh Bapat
Discussion: https://postgr.es/m/bf47888585149f83b276861a1662f7e4@postgrespro.ru
Backpatch-through: 12
This commit is contained in:
Michael Paquier 2024-02-19 11:38:47 +09:00
parent 1d577f2eaa
commit b5cb6022bb
8 changed files with 69 additions and 2 deletions

View File

@ -654,7 +654,7 @@ intoasc(interval * i, char *str)
if (!tmp)
return -errno;
memcpy(str, tmp, strlen(tmp));
strcpy(str, tmp);
free(tmp);
return 0;
}

View File

@ -4,6 +4,8 @@
/dec_test.c
/describe
/describe.c
/intoasc
/intoasc.c
/rfmtdate
/rfmtdate.c
/rfmtlong

View File

@ -16,7 +16,8 @@ TESTS = test_informix test_informix.c \
rnull rnull.c \
sqlda sqlda.c \
describe describe.c \
charfuncs charfuncs.c
charfuncs charfuncs.c \
intoasc intoasc.c
all: $(TESTS)

View File

@ -0,0 +1,21 @@
#include <stdio.h>
#include <stdlib.h>
#include "pgtypes_interval.h"
EXEC SQL BEGIN DECLARE SECTION;
char dirty_str[100] = "aaaaaaaaa_bbbbbbbb_ccccccccc_ddddddddd_";
interval *interval_ptr;
EXEC SQL END DECLARE SECTION;
int main()
{
interval_ptr = (interval *) malloc(sizeof(interval));
interval_ptr->time = 100000000;
interval_ptr->month = 240;
printf("dirty_str contents before intoasc: %s\n", dirty_str);
intoasc(interval_ptr, dirty_str);
printf("dirty_str contents after intoasc: %s\n", dirty_str);
return 0;
}

View File

@ -7,6 +7,7 @@ test: compat_informix/sqlda
test: compat_informix/describe
test: compat_informix/test_informix
test: compat_informix/test_informix2
test: compat_informix/intoasc
test: compat_oracle/char_array
test: connect/test2
test: connect/test3

View File

@ -0,0 +1,40 @@
/* Processed by ecpg (regression mode) */
/* These include files are added by the preprocessor */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* Needed for informix compatibility */
#include <ecpg_informix.h>
/* End of automatic include section */
#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
#line 1 "intoasc.pgc"
#include <stdio.h>
#include <stdlib.h>
#include "pgtypes_interval.h"
/* exec sql begin declare section */
#line 7 "intoasc.pgc"
char dirty_str [ 100 ] = "aaaaaaaaa_bbbbbbbb_ccccccccc_ddddddddd_" ;
#line 8 "intoasc.pgc"
interval * interval_ptr ;
/* exec sql end declare section */
#line 9 "intoasc.pgc"
int main()
{
interval_ptr = (interval *) malloc(sizeof(interval));
interval_ptr->time = 100000000;
interval_ptr->month = 240;
printf("dirty_str contents before intoasc: %s\n", dirty_str);
intoasc(interval_ptr, dirty_str);
printf("dirty_str contents after intoasc: %s\n", dirty_str);
return 0;
}

View File

@ -0,0 +1,2 @@
dirty_str contents before intoasc: aaaaaaaaa_bbbbbbbb_ccccccccc_ddddddddd_
dirty_str contents after intoasc: @ 20 years 1 min 40 secs