#include <stdarg.h>
|
#include <stdarg.h>
|
#ifdef __unix__
|
#ifdef __unix__
|
#include <sys/types.h>
|
#include <sys/types.h>
|
#endif
|
#endif
|
|
|
extern void abort (void);
|
extern void abort (void);
|
|
|
extern int inside_main;
|
extern int inside_main;
|
void *chk_fail_buf[256] __attribute__((aligned (16)));
|
void *chk_fail_buf[256] __attribute__((aligned (16)));
|
volatile int chk_fail_allowed, chk_calls;
|
volatile int chk_fail_allowed, chk_calls;
|
volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
|
volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed;
|
volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
|
volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed;
|
volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed;
|
volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed;
|
volatile int sprintf_disallowed, vsprintf_disallowed;
|
volatile int sprintf_disallowed, vsprintf_disallowed;
|
volatile int snprintf_disallowed, vsnprintf_disallowed;
|
volatile int snprintf_disallowed, vsnprintf_disallowed;
|
extern __SIZE_TYPE__ strlen (const char *);
|
extern __SIZE_TYPE__ strlen (const char *);
|
extern int vsprintf (char *, const char *, va_list);
|
extern int vsprintf (char *, const char *, va_list);
|
|
|
void __attribute__((noreturn))
|
void __attribute__((noreturn))
|
__chk_fail (void)
|
__chk_fail (void)
|
{
|
{
|
if (chk_fail_allowed)
|
if (chk_fail_allowed)
|
__builtin_longjmp (chk_fail_buf, 1);
|
__builtin_longjmp (chk_fail_buf, 1);
|
abort ();
|
abort ();
|
}
|
}
|
|
|
void *
|
void *
|
memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
|
memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
|
{
|
{
|
const char *srcp;
|
const char *srcp;
|
char *dstp;
|
char *dstp;
|
|
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (memcpy_disallowed && inside_main)
|
if (memcpy_disallowed && inside_main)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
|
|
srcp = src;
|
srcp = src;
|
dstp = dst;
|
dstp = dst;
|
while (n-- != 0)
|
while (n-- != 0)
|
*dstp++ = *srcp++;
|
*dstp++ = *srcp++;
|
|
|
return dst;
|
return dst;
|
}
|
}
|
|
|
void *
|
void *
|
__memcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
__memcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into memcpy. */
|
/* If size is -1, GCC should always optimize the call into memcpy. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (n > size)
|
if (n > size)
|
__chk_fail ();
|
__chk_fail ();
|
return memcpy (dst, src, n);
|
return memcpy (dst, src, n);
|
}
|
}
|
|
|
void *
|
void *
|
mempcpy (void *dst, const void *src, __SIZE_TYPE__ n)
|
mempcpy (void *dst, const void *src, __SIZE_TYPE__ n)
|
{
|
{
|
const char *srcp;
|
const char *srcp;
|
char *dstp;
|
char *dstp;
|
|
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (mempcpy_disallowed && inside_main)
|
if (mempcpy_disallowed && inside_main)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
|
|
srcp = src;
|
srcp = src;
|
dstp = dst;
|
dstp = dst;
|
while (n-- != 0)
|
while (n-- != 0)
|
*dstp++ = *srcp++;
|
*dstp++ = *srcp++;
|
|
|
return dstp;
|
return dstp;
|
}
|
}
|
|
|
void *
|
void *
|
__mempcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
__mempcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into mempcpy. */
|
/* If size is -1, GCC should always optimize the call into mempcpy. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (n > size)
|
if (n > size)
|
__chk_fail ();
|
__chk_fail ();
|
return mempcpy (dst, src, n);
|
return mempcpy (dst, src, n);
|
}
|
}
|
|
|
void *
|
void *
|
memmove (void *dst, const void *src, __SIZE_TYPE__ n)
|
memmove (void *dst, const void *src, __SIZE_TYPE__ n)
|
{
|
{
|
const char *srcp;
|
const char *srcp;
|
char *dstp;
|
char *dstp;
|
|
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (memmove_disallowed && inside_main)
|
if (memmove_disallowed && inside_main)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
|
|
srcp = src;
|
srcp = src;
|
dstp = dst;
|
dstp = dst;
|
if (srcp < dstp)
|
if (srcp < dstp)
|
while (n-- != 0)
|
while (n-- != 0)
|
dstp[n] = srcp[n];
|
dstp[n] = srcp[n];
|
else
|
else
|
while (n-- != 0)
|
while (n-- != 0)
|
*dstp++ = *srcp++;
|
*dstp++ = *srcp++;
|
|
|
return dst;
|
return dst;
|
}
|
}
|
|
|
void *
|
void *
|
__memmove_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
__memmove_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into memmove. */
|
/* If size is -1, GCC should always optimize the call into memmove. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (n > size)
|
if (n > size)
|
__chk_fail ();
|
__chk_fail ();
|
return memmove (dst, src, n);
|
return memmove (dst, src, n);
|
}
|
}
|
|
|
void *
|
void *
|
memset (void *dst, int c, __SIZE_TYPE__ n)
|
memset (void *dst, int c, __SIZE_TYPE__ n)
|
{
|
{
|
/* Single-byte memsets should be done inline when optimisation
|
/* Single-byte memsets should be done inline when optimisation
|
is enabled. */
|
is enabled. */
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (memset_disallowed && inside_main && n < 2)
|
if (memset_disallowed && inside_main && n < 2)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
|
|
while (n-- != 0)
|
while (n-- != 0)
|
n[(char *) dst] = c;
|
n[(char *) dst] = c;
|
|
|
return dst;
|
return dst;
|
}
|
}
|
|
|
void *
|
void *
|
__memset_chk (void *dst, int c, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
__memset_chk (void *dst, int c, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into memset. */
|
/* If size is -1, GCC should always optimize the call into memset. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (n > size)
|
if (n > size)
|
__chk_fail ();
|
__chk_fail ();
|
return memset (dst, c, n);
|
return memset (dst, c, n);
|
}
|
}
|
|
|
char *
|
char *
|
strcpy (char *d, const char *s)
|
strcpy (char *d, const char *s)
|
{
|
{
|
char *r = d;
|
char *r = d;
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (strcpy_disallowed && inside_main)
|
if (strcpy_disallowed && inside_main)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
while ((*d++ = *s++));
|
while ((*d++ = *s++));
|
return r;
|
return r;
|
}
|
}
|
|
|
char *
|
char *
|
__strcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
|
__strcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into strcpy. */
|
/* If size is -1, GCC should always optimize the call into strcpy. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (strlen (s) >= size)
|
if (strlen (s) >= size)
|
__chk_fail ();
|
__chk_fail ();
|
return strcpy (d, s);
|
return strcpy (d, s);
|
}
|
}
|
|
|
char *
|
char *
|
stpcpy (char *dst, const char *src)
|
stpcpy (char *dst, const char *src)
|
{
|
{
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (stpcpy_disallowed && inside_main)
|
if (stpcpy_disallowed && inside_main)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
|
|
while (*src != 0)
|
while (*src != 0)
|
*dst++ = *src++;
|
*dst++ = *src++;
|
|
|
*dst = 0;
|
*dst = 0;
|
return dst;
|
return dst;
|
}
|
}
|
|
|
char *
|
char *
|
__stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
|
__stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into stpcpy. */
|
/* If size is -1, GCC should always optimize the call into stpcpy. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (strlen (s) >= size)
|
if (strlen (s) >= size)
|
__chk_fail ();
|
__chk_fail ();
|
return stpcpy (d, s);
|
return stpcpy (d, s);
|
}
|
}
|
|
|
char *
|
char *
|
strncpy (char *s1, const char *s2, __SIZE_TYPE__ n)
|
strncpy (char *s1, const char *s2, __SIZE_TYPE__ n)
|
{
|
{
|
char *dest = s1;
|
char *dest = s1;
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (strncpy_disallowed && inside_main)
|
if (strncpy_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
for (; *s2 && n; n--)
|
for (; *s2 && n; n--)
|
*s1++ = *s2++;
|
*s1++ = *s2++;
|
while (n--)
|
while (n--)
|
*s1++ = 0;
|
*s1++ = 0;
|
return dest;
|
return dest;
|
}
|
}
|
|
|
char *
|
char *
|
__strncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
__strncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into strncpy. */
|
/* If size is -1, GCC should always optimize the call into strncpy. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (n > size)
|
if (n > size)
|
__chk_fail ();
|
__chk_fail ();
|
return strncpy (s1, s2, n);
|
return strncpy (s1, s2, n);
|
}
|
}
|
|
|
char *
|
char *
|
strcat (char *dst, const char *src)
|
strcat (char *dst, const char *src)
|
{
|
{
|
char *p = dst;
|
char *p = dst;
|
|
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (strcat_disallowed && inside_main)
|
if (strcat_disallowed && inside_main)
|
abort ();
|
abort ();
|
#endif
|
#endif
|
|
|
while (*p)
|
while (*p)
|
p++;
|
p++;
|
while ((*p++ = *src++))
|
while ((*p++ = *src++))
|
;
|
;
|
return dst;
|
return dst;
|
}
|
}
|
|
|
char *
|
char *
|
__strcat_chk (char *d, const char *s, __SIZE_TYPE__ size)
|
__strcat_chk (char *d, const char *s, __SIZE_TYPE__ size)
|
{
|
{
|
/* If size is -1, GCC should always optimize the call into strcat. */
|
/* If size is -1, GCC should always optimize the call into strcat. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (strlen (d) + strlen (s) >= size)
|
if (strlen (d) + strlen (s) >= size)
|
__chk_fail ();
|
__chk_fail ();
|
return strcat (d, s);
|
return strcat (d, s);
|
}
|
}
|
|
|
char *
|
char *
|
strncat (char *s1, const char *s2, __SIZE_TYPE__ n)
|
strncat (char *s1, const char *s2, __SIZE_TYPE__ n)
|
{
|
{
|
char *dest = s1;
|
char *dest = s1;
|
char c;
|
char c;
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (strncat_disallowed && inside_main)
|
if (strncat_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
while (*s1) s1++;
|
while (*s1) s1++;
|
c = '\0';
|
c = '\0';
|
while (n > 0)
|
while (n > 0)
|
{
|
{
|
c = *s2++;
|
c = *s2++;
|
*s1++ = c;
|
*s1++ = c;
|
if (c == '\0')
|
if (c == '\0')
|
return dest;
|
return dest;
|
n--;
|
n--;
|
}
|
}
|
if (c != '\0')
|
if (c != '\0')
|
*s1 = '\0';
|
*s1 = '\0';
|
return dest;
|
return dest;
|
}
|
}
|
|
|
char *
|
char *
|
__strncat_chk (char *d, const char *s, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
__strncat_chk (char *d, const char *s, __SIZE_TYPE__ n, __SIZE_TYPE__ size)
|
{
|
{
|
__SIZE_TYPE__ len = strlen (d), n1 = n;
|
__SIZE_TYPE__ len = strlen (d), n1 = n;
|
const char *s1 = s;
|
const char *s1 = s;
|
|
|
/* If size is -1, GCC should always optimize the call into strncat. */
|
/* If size is -1, GCC should always optimize the call into strncat. */
|
if (size == (__SIZE_TYPE__) -1)
|
if (size == (__SIZE_TYPE__) -1)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
while (len < size && n1 > 0)
|
while (len < size && n1 > 0)
|
{
|
{
|
if (*s1++ == '\0')
|
if (*s1++ == '\0')
|
break;
|
break;
|
++len;
|
++len;
|
--n1;
|
--n1;
|
}
|
}
|
|
|
if (len >= size)
|
if (len >= size)
|
__chk_fail ();
|
__chk_fail ();
|
return strncat (d, s, n);
|
return strncat (d, s, n);
|
}
|
}
|
|
|
/* No chk test in GCC testsuite needs more bytes than this.
|
/* No chk test in GCC testsuite needs more bytes than this.
|
As we can't expect vsnprintf to be available on the target,
|
As we can't expect vsnprintf to be available on the target,
|
assume 4096 bytes is enough. */
|
assume 4096 bytes is enough. */
|
static char chk_sprintf_buf[4096];
|
static char chk_sprintf_buf[4096];
|
|
|
int
|
int
|
__sprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, ...)
|
__sprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, ...)
|
{
|
{
|
int ret;
|
int ret;
|
va_list ap;
|
va_list ap;
|
|
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
sprintf. */
|
sprintf. */
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (sprintf_disallowed && inside_main)
|
if (sprintf_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
va_start (ap, fmt);
|
va_start (ap, fmt);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
va_end (ap);
|
va_end (ap);
|
if (ret >= 0)
|
if (ret >= 0)
|
{
|
{
|
if (ret >= size)
|
if (ret >= size)
|
__chk_fail ();
|
__chk_fail ();
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
|
|
int
|
int
|
__vsprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt,
|
__vsprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt,
|
va_list ap)
|
va_list ap)
|
{
|
{
|
int ret;
|
int ret;
|
|
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
vsprintf. */
|
vsprintf. */
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (vsprintf_disallowed && inside_main)
|
if (vsprintf_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
if (ret >= 0)
|
if (ret >= 0)
|
{
|
{
|
if (ret >= size)
|
if (ret >= size)
|
__chk_fail ();
|
__chk_fail ();
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
|
|
int
|
int
|
__snprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
|
__snprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
|
const char *fmt, ...)
|
const char *fmt, ...)
|
{
|
{
|
int ret;
|
int ret;
|
va_list ap;
|
va_list ap;
|
|
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
snprintf. */
|
snprintf. */
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (size < len)
|
if (size < len)
|
__chk_fail ();
|
__chk_fail ();
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (snprintf_disallowed && inside_main)
|
if (snprintf_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
va_start (ap, fmt);
|
va_start (ap, fmt);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
va_end (ap);
|
va_end (ap);
|
if (ret >= 0)
|
if (ret >= 0)
|
{
|
{
|
if (ret < len)
|
if (ret < len)
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
else
|
else
|
{
|
{
|
memcpy (str, chk_sprintf_buf, len - 1);
|
memcpy (str, chk_sprintf_buf, len - 1);
|
str[len - 1] = '\0';
|
str[len - 1] = '\0';
|
}
|
}
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
|
|
int
|
int
|
__vsnprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
|
__vsnprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size,
|
const char *fmt, va_list ap)
|
const char *fmt, va_list ap)
|
{
|
{
|
int ret;
|
int ret;
|
|
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
/* If size is -1 and flag 0, GCC should always optimize the call into
|
vsnprintf. */
|
vsnprintf. */
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
if (size == (__SIZE_TYPE__) -1 && flag == 0)
|
abort ();
|
abort ();
|
++chk_calls;
|
++chk_calls;
|
if (size < len)
|
if (size < len)
|
__chk_fail ();
|
__chk_fail ();
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (vsnprintf_disallowed && inside_main)
|
if (vsnprintf_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
if (ret >= 0)
|
if (ret >= 0)
|
{
|
{
|
if (ret < len)
|
if (ret < len)
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
else
|
else
|
{
|
{
|
memcpy (str, chk_sprintf_buf, len - 1);
|
memcpy (str, chk_sprintf_buf, len - 1);
|
str[len - 1] = '\0';
|
str[len - 1] = '\0';
|
}
|
}
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
|
|
int
|
int
|
snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...)
|
snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...)
|
{
|
{
|
int ret;
|
int ret;
|
va_list ap;
|
va_list ap;
|
|
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (snprintf_disallowed && inside_main)
|
if (snprintf_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
va_start (ap, fmt);
|
va_start (ap, fmt);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
va_end (ap);
|
va_end (ap);
|
if (ret >= 0)
|
if (ret >= 0)
|
{
|
{
|
if (ret < len)
|
if (ret < len)
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
else if (len)
|
else if (len)
|
{
|
{
|
memcpy (str, chk_sprintf_buf, len - 1);
|
memcpy (str, chk_sprintf_buf, len - 1);
|
str[len - 1] = '\0';
|
str[len - 1] = '\0';
|
}
|
}
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
|
|
/* uClibc's vsprintf calls vsnprintf. */
|
/* uClibc's vsprintf calls vsnprintf. */
|
#ifndef __UCLIBC__
|
#ifndef __UCLIBC__
|
int
|
int
|
vsnprintf (char *str, __SIZE_TYPE__ len, const char *fmt, va_list ap)
|
vsnprintf (char *str, __SIZE_TYPE__ len, const char *fmt, va_list ap)
|
{
|
{
|
int ret;
|
int ret;
|
|
|
#ifdef __OPTIMIZE__
|
#ifdef __OPTIMIZE__
|
if (vsnprintf_disallowed && inside_main)
|
if (vsnprintf_disallowed && inside_main)
|
abort();
|
abort();
|
#endif
|
#endif
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
ret = vsprintf (chk_sprintf_buf, fmt, ap);
|
if (ret >= 0)
|
if (ret >= 0)
|
{
|
{
|
if (ret < len)
|
if (ret < len)
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
memcpy (str, chk_sprintf_buf, ret + 1);
|
else if (len)
|
else if (len)
|
{
|
{
|
memcpy (str, chk_sprintf_buf, len - 1);
|
memcpy (str, chk_sprintf_buf, len - 1);
|
str[len - 1] = '\0';
|
str[len - 1] = '\0';
|
}
|
}
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
#endif
|
#endif
|
|
|