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