mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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:
		@@ -654,7 +654,7 @@ intoasc(interval * i, char *str)
 | 
				
			|||||||
	if (!tmp)
 | 
						if (!tmp)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(str, tmp, strlen(tmp));
 | 
						strcpy(str, tmp);
 | 
				
			||||||
	free(tmp);
 | 
						free(tmp);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@
 | 
				
			|||||||
/dec_test.c
 | 
					/dec_test.c
 | 
				
			||||||
/describe
 | 
					/describe
 | 
				
			||||||
/describe.c
 | 
					/describe.c
 | 
				
			||||||
 | 
					/intoasc
 | 
				
			||||||
 | 
					/intoasc.c
 | 
				
			||||||
/rfmtdate
 | 
					/rfmtdate
 | 
				
			||||||
/rfmtdate.c
 | 
					/rfmtdate.c
 | 
				
			||||||
/rfmtlong
 | 
					/rfmtlong
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,8 @@ TESTS = test_informix test_informix.c \
 | 
				
			|||||||
        rnull rnull.c \
 | 
					        rnull rnull.c \
 | 
				
			||||||
        sqlda sqlda.c \
 | 
					        sqlda sqlda.c \
 | 
				
			||||||
        describe describe.c \
 | 
					        describe describe.c \
 | 
				
			||||||
        charfuncs charfuncs.c
 | 
					        charfuncs charfuncs.c \
 | 
				
			||||||
 | 
					        intoasc intoasc.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
all: $(TESTS)
 | 
					all: $(TESTS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								src/interfaces/ecpg/test/compat_informix/intoasc.pgc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/interfaces/ecpg/test/compat_informix/intoasc.pgc
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,6 +7,7 @@ test: compat_informix/sqlda
 | 
				
			|||||||
test: compat_informix/describe
 | 
					test: compat_informix/describe
 | 
				
			||||||
test: compat_informix/test_informix
 | 
					test: compat_informix/test_informix
 | 
				
			||||||
test: compat_informix/test_informix2
 | 
					test: compat_informix/test_informix2
 | 
				
			||||||
 | 
					test: compat_informix/intoasc
 | 
				
			||||||
test: compat_oracle/char_array
 | 
					test: compat_oracle/char_array
 | 
				
			||||||
test: connect/test2
 | 
					test: connect/test2
 | 
				
			||||||
test: connect/test3
 | 
					test: connect/test3
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								src/interfaces/ecpg/test/expected/compat_informix-intoasc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/interfaces/ecpg/test/expected/compat_informix-intoasc.c
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					dirty_str contents before intoasc: aaaaaaaaa_bbbbbbbb_ccccccccc_ddddddddd_
 | 
				
			||||||
 | 
					dirty_str contents after intoasc: @ 20 years 1 min 40 secs
 | 
				
			||||||
		Reference in New Issue
	
	Block a user