mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
![Brandon Casey](/assets/img/avatar_default.png)
Some platforms provide a horribly broken snprintf. More broken than the platforms that return -1 when there is too little space in the target buffer for the formatted string. Some platforms provide an snprintf which _always_ returns the number of characters transmitted to the buffer, regardless of whether there was enough space or not. IRIX 6.5 is such a platform. IRIX does have a working snprintf(), but it is only provided when _NO_XOPEN5 evaluates to zero, and this only happens if _XOPEN_SOURCE is defined, but definition of _XOPEN_SOURCE prevents inclusion of many other common functions and defines. So it must be avoided. Work around these horribly broken snprintf implementations by detecting an snprintf call which results in the number of transmitted characters exactly equal to the length of our buffer and retrying with a larger buffer just to be safe. Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil> Acked-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>
58 lines
1.1 KiB
C
58 lines
1.1 KiB
C
#include "../git-compat-util.h"
|
|
|
|
/*
|
|
* The size parameter specifies the available space, i.e. includes
|
|
* the trailing NUL byte; but Windows's vsnprintf expects the
|
|
* number of characters to write without the trailing NUL.
|
|
*/
|
|
#ifndef SNPRINTF_SIZE_CORR
|
|
#define SNPRINTF_SIZE_CORR 0
|
|
#endif
|
|
|
|
#undef vsnprintf
|
|
int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
|
|
{
|
|
char *s;
|
|
int ret = -1;
|
|
|
|
if (maxsize > 0) {
|
|
ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
|
|
if (ret == maxsize-1)
|
|
ret = -1;
|
|
/* Windows does not NUL-terminate if result fills buffer */
|
|
str[maxsize-1] = 0;
|
|
}
|
|
if (ret != -1)
|
|
return ret;
|
|
|
|
s = NULL;
|
|
if (maxsize < 128)
|
|
maxsize = 128;
|
|
|
|
while (ret == -1) {
|
|
maxsize *= 4;
|
|
str = realloc(s, maxsize);
|
|
if (! str)
|
|
break;
|
|
s = str;
|
|
ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
|
|
if (ret == maxsize-1)
|
|
ret = -1;
|
|
}
|
|
free(s);
|
|
return ret;
|
|
}
|
|
|
|
int git_snprintf(char *str, size_t maxsize, const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
int ret;
|
|
|
|
va_start(ap, format);
|
|
ret = git_vsnprintf(str, maxsize, format, ap);
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
}
|
|
|