Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/*
2
 * Revision 12: http://theos.com/~deraadt/snprintf.c
3
 *
4
 * Copyright (c) 1997 Theo de Raadt
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
#include <sys/param.h>
28
#include <sys/types.h>
29
#include <sys/mman.h>
30
#include <signal.h>
31
#include <stdio.h>
32
#if __STDC__
33
#include <stdarg.h>
34
#include <stdlib.h>
35
#else
36
#include <varargs.h>
37
#endif
38
#include <setjmp.h>
39
#include <unistd.h>
40
#include <string.h>
41
 
42
#ifndef roundup
43
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
44
#endif
45
 
46
#ifdef __sgi
47
#define size_t ssize_t
48
#endif
49
 
50
static int pgsize;
51
static char *curobj;
52
static int caught;
53
static sigjmp_buf bail;
54
 
55
#define EXTRABYTES      2       /* XXX: why 2? you don't want to know */
56
 
57
static char *
58
msetup(str, n)
59
        char *str;
60
        size_t n;
61
{
62
        char *e;
63
 
64
        if (n == 0)
65
                return NULL;
66
        if (pgsize == 0)
67
                pgsize = getpagesize();
68
        curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2);
69
        if (curobj == NULL)
70
                return NULL;
71
        e = curobj + n + EXTRABYTES;
72
        e = (char *)roundup((unsigned long)e, pgsize);
73
        if (mprotect(e, pgsize, PROT_NONE) == -1) {
74
                free(curobj);
75
                curobj = NULL;
76
                return NULL;
77
        }
78
        e = e - n - EXTRABYTES;
79
        *e = '\0';
80
        return (e);
81
}
82
 
83
static void
84
  mcatch( int a )
85
{
86
        siglongjmp(bail, 1);
87
}
88
 
89
static void
90
mcleanup(str, n, p)
91
        char *str;
92
        size_t n;
93
        char *p;
94
{
95
        strncpy(str, p, n-1);
96
        str[n-1] = '\0';
97
        if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
98
            PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
99
                mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
100
                    PROT_READ|PROT_WRITE);
101
        free(curobj);
102
}
103
 
104
int
105
#if __STDC__
106
vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
107
#else
108
vsnprintf(str, n, fmt, ap)
109
        char *str;
110
        size_t n;
111
        char *fmt;
112
        char *ap;
113
#endif
114
{
115
        struct sigaction osa, nsa;
116
        char *p;
117
        int ret = n + 1;        /* if we bail, indicated we overflowed */
118
 
119
        memset(&nsa, 0, sizeof nsa);
120
        nsa.sa_handler = mcatch;
121
        sigemptyset(&nsa.sa_mask);
122
 
123
        p = msetup(str, n);
124
        if (p == NULL) {
125
                *str = '\0';
126
                return 0;
127
        }
128
        if (sigsetjmp(bail, 1) == 0) {
129
                if (sigaction(SIGSEGV, &nsa, &osa) == -1) {
130
                        mcleanup(str, n, p);
131
                        return (0);
132
                }
133
                ret = vsprintf(p, fmt, ap);
134
        }
135
        mcleanup(str, n, p);
136
        (void) sigaction(SIGSEGV, &osa, NULL);
137
        return (ret);
138
}
139
 
140
int
141
#if __STDC__
142
snprintf(char *str, size_t n, char const *fmt, ...)
143
#else
144
snprintf(str, n, fmt, va_alist)
145
        char *str;
146
        size_t n;
147
        char *fmt;
148
        va_dcl
149
#endif
150
{
151
        va_list ap;
152
#if __STDC__
153
        va_start(ap, fmt);
154
#else
155
        va_start(ap);
156
#endif
157
 
158
        return (vsnprintf(str, n, fmt, ap));
159
        va_end(ap);
160
}
161
 
162
 
163