| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | /* snprintf() wrappers.  If the platform has vsnprintf, we use it, else we
 | 
					
						
							|  |  |  |    emulate it in a half-hearted way.  Even if the platform has it, we wrap | 
					
						
							|  |  |  |    it because platforms differ in what vsnprintf does in case the buffer | 
					
						
							|  |  |  |    is too small:  C99 behavior is to return the number of characters that | 
					
						
							|  |  |  |    would have been written had the buffer not been too small, and to set | 
					
						
							|  |  |  |    the last byte of the buffer to \0.  At least MS _vsnprintf returns a | 
					
						
							|  |  |  |    negative value instead, and fills the entire buffer with non-\0 data. | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  |    The wrappers ensure that str[size-1] is always \0 upon return. | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  |    PyOS_snprintf and PyOS_vsnprintf never write more than size bytes | 
					
						
							|  |  |  |    (including the trailing '\0') into str. | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  |    If the platform doesn't have vsnprintf, and the buffer size needed to | 
					
						
							|  |  |  |    avoid truncation exceeds size by more than 512, Python aborts with a | 
					
						
							|  |  |  |    Py_FatalError. | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  |    Return value (rv): | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	When 0 <= rv < size, the output conversion was unexceptional, and | 
					
						
							|  |  |  | 	rv characters were written to str (excluding a trailing \0 byte at | 
					
						
							|  |  |  | 	str[rv]). | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	When rv >= size, output conversion was truncated, and a buffer of | 
					
						
							|  |  |  | 	size rv+1 would have been needed to avoid truncation.  str[size-1] | 
					
						
							|  |  |  | 	is \0 in this case. | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	When rv < 0, "something bad happened".  str[size-1] is \0 in this | 
					
						
							|  |  |  | 	case too, but the rest of str is unreliable.  It could be that | 
					
						
							|  |  |  | 	an error in format codes was detected by libc, or on platforms | 
					
						
							|  |  |  | 	with a non-C99 vsnprintf simply that the buffer wasn't big enough | 
					
						
							|  |  |  | 	to avoid truncation, or on platforms without any vsnprintf that | 
					
						
							|  |  |  | 	PyMem_Malloc couldn't obtain space for a temp buffer. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    CAUTION:  Unlike C99, str != NULL and size > 0 are required. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | int | 
					
						
							|  |  |  | PyOS_snprintf(char *str, size_t size, const  char  *format, ...) | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	int rc; | 
					
						
							|  |  |  | 	va_list va; | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	va_start(va, format); | 
					
						
							|  |  |  | 	rc = PyOS_vsnprintf(str, size, format, va); | 
					
						
							|  |  |  | 	va_end(va); | 
					
						
							|  |  |  | 	return rc; | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | int | 
					
						
							|  |  |  | PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va) | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	int len;  /* # bytes written, excluding \0 */ | 
					
						
							|  |  |  | #ifndef HAVE_SNPRINTF
 | 
					
						
							|  |  |  | 	char *buffer; | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	assert(str != NULL); | 
					
						
							|  |  |  | 	assert(size > 0); | 
					
						
							|  |  |  | 	assert(format != NULL); | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | #ifdef HAVE_SNPRINTF
 | 
					
						
							|  |  |  | 	len = vsnprintf(str, size, format, va); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	/* Emulate it. */ | 
					
						
							| 
									
										
										
										
											2001-12-21 16:32:15 +00:00
										 |  |  | 	buffer = PyMem_MALLOC(size + 512); | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	if (buffer == NULL) { | 
					
						
							|  |  |  | 		len = -666; | 
					
						
							|  |  |  | 		goto Done; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = vsprintf(buffer, format, va); | 
					
						
							|  |  |  | 	if (len < 0) | 
					
						
							|  |  |  | 		/* ignore the error */; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	else if ((size_t)len >= size + 512) | 
					
						
							|  |  |  | 		Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		const size_t to_copy = (size_t)len < size ? | 
					
						
							|  |  |  | 					(size_t)len : size - 1; | 
					
						
							|  |  |  | 		assert(to_copy < size); | 
					
						
							|  |  |  | 		memcpy(str, buffer, to_copy); | 
					
						
							|  |  |  | 		str[to_copy] = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-12-21 16:32:15 +00:00
										 |  |  | 	PyMem_FREE(buffer); | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | Done: | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-12-03 00:43:33 +00:00
										 |  |  | 	str[size-1] = '\0'; | 
					
						
							|  |  |  | 	return len; | 
					
						
							| 
									
										
										
										
											2001-07-31 13:24:44 +00:00
										 |  |  | } |