1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
*
* $Id: snprintf.c,v 11.18 2004/09/22 03:32:43 bostic Exp $
*/
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* Declare STDERR_FILENO. */
#endif
#include "db_int.h"
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
static void sprintf_overflow __P((void));
static int sprintf_retcharpnt __P((void));
#endif
/*
* snprintf --
* Bounded version of sprintf.
*
* PUBLIC: #ifndef HAVE_SNPRINTF
* PUBLIC: int snprintf __P((char *, size_t, const char *, ...));
* PUBLIC: #endif
*/
#ifndef HAVE_SNPRINTF
int
#ifdef STDC_HEADERS
snprintf(char *str, size_t n, const char *fmt, ...)
#else
snprintf(str, n, fmt, va_alist)
char *str;
size_t n;
const char *fmt;
va_dcl
#endif
{
static int ret_charpnt = -1;
va_list ap;
size_t len;
if (ret_charpnt == -1)
ret_charpnt = sprintf_retcharpnt();
#ifdef STDC_HEADERS
va_start(ap, fmt);
#else
va_start(ap);
#endif
len = (size_t)vsprintf(str, fmt, ap);
if (ret_charpnt)
len = strlen(str);
va_end(ap);
if (len >= n) {
sprintf_overflow();
/* NOTREACHED */
}
return ((int)len);
}
#endif
/*
* vsnprintf --
* Bounded version of vsprintf.
*
* PUBLIC: #ifndef HAVE_VSNPRINTF
* PUBLIC: int vsnprintf __P((char *, size_t, const char *, va_list));
* PUBLIC: #endif
*/
#ifndef HAVE_VSNPRINTF
int
vsnprintf(str, n, fmt, ap)
char *str;
size_t n;
const char *fmt;
va_list ap;
{
static int ret_charpnt = -1;
size_t len;
if (ret_charpnt == -1)
ret_charpnt = sprintf_retcharpnt();
len = (size_t)vsprintf(str, fmt, ap);
if (ret_charpnt)
len = strlen(str);
if (len >= n) {
sprintf_overflow();
/* NOTREACHED */
}
return ((int)len);
}
#endif
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
static void
sprintf_overflow()
{
/*
* !!!
* We're potentially manipulating strings handed us by the application,
* and on systems without a real snprintf() the sprintf() calls could
* have overflowed the buffer. We can't do anything about it now, but
* we don't want to return control to the application, we might have
* overwritten the stack with a Trojan horse. We're not trying to do
* anything recoverable here because systems without snprintf support
* are pretty rare anymore.
*/
#define OVERFLOW_ERROR "internal buffer overflow, process ended\n"
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
(void)write(STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1);
/* Be polite. */
exit(1);
/* But firm. */
abort();
/* NOTREACHED */
}
static int
sprintf_retcharpnt()
{
int ret_charpnt;
char buf[10];
/*
* Some old versions of sprintf return a pointer to the first argument
* instead of a character count. Assume the return value of snprintf,
* vsprintf, etc. will be the same as sprintf, and check the easy one.
*
* We do this test at run-time because it's not a test we can do in a
* cross-compilation environment.
*/
ret_charpnt =
(int)sprintf(buf, "123") != 3 ||
(int)sprintf(buf, "123456789") != 9 ||
(int)sprintf(buf, "1234") != 4;
return (ret_charpnt);
}
#endif
|