10a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen/* 20a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * Revision 12: http://theos.com/~deraadt/snprintf.c 30a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * 40a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * Copyright (c) 1997 Theo de Raadt 50a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * 60a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * Redistribution and use in source and binary forms, with or without 70a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * modification, are permitted provided that the following conditions 80a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * are met: 90a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * 1. Redistributions of source code must retain the above copyright 100a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * notice, this list of conditions and the following disclaimer. 110a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * 2. Redistributions in binary form must reproduce the above copyright 120a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * notice, this list of conditions and the following disclaimer in the 130a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * documentation and/or other materials provided with the distribution. 140a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * 150a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 160a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 170a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 180a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 190a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 200a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 210a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 220a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 230a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 240a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 250a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen */ 260a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 277ac913362770b9f15093bd43769068d966bf913fJouk Jansen#ifndef __VMS 287ac913362770b9f15093bd43769068d966bf913fJouk Jansen# include <sys/param.h> 297ac913362770b9f15093bd43769068d966bf913fJouk Jansen#endif 300a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <sys/types.h> 310a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <sys/mman.h> 320a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <signal.h> 330a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <stdio.h> 340a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#if __STDC__ 350a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <stdarg.h> 360a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <stdlib.h> 370a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#else 380a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <varargs.h> 390a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#endif 400a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <setjmp.h> 410a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <unistd.h> 420a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#include <string.h> 430a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 440a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#ifndef roundup 450a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 460a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#endif 470a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 480a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#ifdef __sgi 490a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#define size_t ssize_t 500a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#endif 510a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 520a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic int pgsize; 530a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic char *curobj; 540a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic int caught; 550a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic sigjmp_buf bail; 560a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 570a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#define EXTRABYTES 2 /* XXX: why 2? you don't want to know */ 580a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 590a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic char * 600a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenmsetup(str, n) 610a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *str; 620a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen size_t n; 630a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen{ 640a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *e; 650a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 660a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (n == 0) 670a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return NULL; 680a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (pgsize == 0) 690a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen pgsize = getpagesize(); 700a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2); 710a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (curobj == NULL) 720a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return NULL; 730a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen e = curobj + n + EXTRABYTES; 740a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen e = (char *)roundup((unsigned long)e, pgsize); 750a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (mprotect(e, pgsize, PROT_NONE) == -1) { 760a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen free(curobj); 770a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen curobj = NULL; 780a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return NULL; 790a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen } 800a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen e = e - n - EXTRABYTES; 810a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen *e = '\0'; 820a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return (e); 830a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen} 840a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 850a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic void 860a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen mcatch( int a ) 870a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen{ 880a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen siglongjmp(bail, 1); 890a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen} 900a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 910a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenstatic void 920a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenmcleanup(str, n, p) 930a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *str; 940a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen size_t n; 950a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *p; 960a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen{ 970a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen strncpy(str, p, n-1); 980a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen str[n-1] = '\0'; 990a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize, 1000a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen PROT_READ|PROT_WRITE|PROT_EXEC) == -1) 1010a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen mprotect((caddr_t)(p + n + EXTRABYTES), pgsize, 1020a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen PROT_READ|PROT_WRITE); 1030a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen free(curobj); 1040a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen} 1050a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1060a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenint 1070a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#if __STDC__ 1080a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenvsnprintf(char *str, size_t n, char const *fmt, va_list ap) 1090a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#else 1100a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenvsnprintf(str, n, fmt, ap) 1110a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *str; 1120a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen size_t n; 1130a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *fmt; 1140a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *ap; 1150a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#endif 1160a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen{ 1170a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen struct sigaction osa, nsa; 1180a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *p; 1190a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen int ret = n + 1; /* if we bail, indicated we overflowed */ 1200a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1210a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen memset(&nsa, 0, sizeof nsa); 1220a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen nsa.sa_handler = mcatch; 1230a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen sigemptyset(&nsa.sa_mask); 1240a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1250a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen p = msetup(str, n); 1260a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (p == NULL) { 1270a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen *str = '\0'; 1280a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return 0; 1290a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen } 1300a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (sigsetjmp(bail, 1) == 0) { 1310a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen if (sigaction(SIGSEGV, &nsa, &osa) == -1) { 1320a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen mcleanup(str, n, p); 1330a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return (0); 1340a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen } 1350a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen ret = vsprintf(p, fmt, ap); 1360a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen } 1370a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen mcleanup(str, n, p); 1380a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen (void) sigaction(SIGSEGV, &osa, NULL); 1390a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return (ret); 1400a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen} 1410a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1420a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansenint 1430a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#if __STDC__ 1440a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansensnprintf(char *str, size_t n, char const *fmt, ...) 1450a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#else 1460a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansensnprintf(str, n, fmt, va_alist) 1470a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *str; 1480a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen size_t n; 1490a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen char *fmt; 1500a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen va_dcl 1510a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#endif 1520a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen{ 1530a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen va_list ap; 1540a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#if __STDC__ 1550a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen va_start(ap, fmt); 1560a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#else 1570a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen va_start(ap); 1580a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen#endif 1590a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1600a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen return (vsnprintf(str, n, fmt, ap)); 1610a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen va_end(ap); 1620a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen} 1630a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1640a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 1650a7fc572a7defdb7f7f23d4288bf8bbbc1ca48bdJouk Jansen 166