source: zzuf/trunk/src/libzzuf/debug.c @ 4231

Last change on this file since 4231 was 4231, checked in by sam, 4 years ago

Fix an overflow in our printf's NULL handling with %p.

  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  debug.c: debugging support
17 */
18
19#include "config.h"
20
21#if defined HAVE_STDINT_H
22#   include <stdint.h>
23#elif defined HAVE_INTTYPES_H
24#   include <inttypes.h>
25#endif
26#include <stdio.h>
27#include <string.h>
28#if defined HAVE_UNISTD_H
29#   include <unistd.h>
30#endif
31#if defined HAVE_IO_H
32#   include <io.h>
33#endif
34#include <errno.h>
35#include <stdarg.h>
36
37#include "debug.h"
38#include "libzzuf.h"
39
40static void mydebug(char const *format, va_list args);
41
42/**
43 * Helper macro to write an integer value to a given file descriptor,
44 * either in base 10 or in hexadecimal.
45 */
46#define WRITE_INT(i, base) \
47    do \
48    { \
49        char buf[128], *b = buf + 127; \
50        if(i <= 0) \
51            append((i = -i) ? "-" : "0", 1); /* XXX: hack here */ \
52        while(i) \
53        { \
54            *b-- = hex2char[i % base]; \
55            i /= base; \
56        } \
57        append(b + 1, (int)(buf + 127 - b)); \
58    } while(0)
59
60/* Temporary buffer for deferred output */
61char debugbuffer[BUFSIZ];
62size_t debugcount = 1;
63
64void _zz_debug(char const *format, ...)
65{
66    va_list args;
67    va_start(args, format);
68    if (_zz_debuglevel >= 1)
69        mydebug(format, args);
70    va_end(args);
71}
72
73void _zz_debug2(char const *format, ...)
74{
75    va_list args;
76    va_start(args, format);
77    if (_zz_debuglevel >= 2)
78        mydebug(format, args);
79    va_end(args);
80}
81
82/**
83 * Format a string, printf-like, and write the resulting data to zzuf's
84 * debug file descriptor _zz_debugfd. If the debug file descriptor is
85 * still -1, this function does nothing.
86 *
87 * This function's code is roughly equivalent to the following *printf
88 * calls, except it only uses signal-safe functions:
89 *  - fprintf(stderr, "** zzuf debug ** ");
90 *  - vfprintf(stderr, format, args);
91 *  - fprintf(stderr, "\n");
92 */
93static inline void append(void const *data, size_t count)
94{
95    if (debugcount + count <= sizeof(debugbuffer))
96    {
97        memcpy(debugbuffer + debugcount, data, count);
98        debugcount += count;
99    }
100}
101
102static void mydebug(char const *format, va_list args)
103{
104    static char const *hex2char = "0123456789abcdef";
105    char const *f;
106    int saved_errno;
107
108    saved_errno = errno;
109
110    /* If there is spare data and the debug fd is open, we send the data */
111    if (debugcount && _zz_debugfd >= 0)
112    {
113        write(_zz_debugfd, debugbuffer, debugcount);
114        debugcount = 0;
115    }
116
117    append("** zzuf debug ** ", 17);
118    for(f = format; *f; f++)
119    {
120        if(*f != '%')
121        {
122            append(f, 1);
123            continue;
124        }
125
126        f++;
127        if(!*f)
128            break;
129
130        if(*f == 'c')
131        {
132            char i = (char)(unsigned char)va_arg(args, int);
133            if(i >= 0x20 && i < 0x7f)
134                append(&i, 1);
135            else if(i == '\n')
136                append("\\n", 2);
137            else if(i == '\t')
138                append("\\t", 2);
139            else if(i == '\r')
140                append("\\r", 2);
141            else
142            {
143                append("\\x", 2);
144                append(hex2char + ((i & 0xf0) >> 4), 1);
145                append(hex2char + (i & 0x0f), 1);
146            }
147        }
148        else if(*f == 'i' || *f == 'd')
149        {
150            int i = va_arg(args, int);
151            WRITE_INT(i, 10);
152        }
153        else if(*f == 'x')
154        {
155            int i = va_arg(args, int);
156            WRITE_INT(i, 16);
157        }
158        else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd'))
159        {
160            long int i = va_arg(args, long int);
161            WRITE_INT(i, 10);
162            f++;
163        }
164        else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd'))
165        {
166            long long int i = va_arg(args, long long int);
167            WRITE_INT(i, 10);
168            f += 2;
169        }
170        else if(f[0] == 'g')
171        {
172            double g = va_arg(args, double), h = 0.0000001;
173            int i = (int)g;
174            WRITE_INT(i, 10);
175            for(i = 0; i < 7; i++)
176            {
177                g = (g - (int)g) * 10;
178                h *= 10;
179                if(g < h)
180                    break;
181                if(i == 0)
182                    append(".", 1);
183                append(hex2char + (int)g, 1);
184            }
185        }
186        else if(f[0] == 'p')
187        {
188            uintptr_t i = va_arg(args, uintptr_t);
189            if(!i)
190                append("NULL", 4);
191            else
192            {
193                append("0x", 2);
194                WRITE_INT(i, 16);
195            }
196        }
197        else if(f[0] == 's')
198        {
199            char *s = va_arg(args, char *);
200            if(!s)
201                append("(nil)", 5);
202            else
203            {
204                int l = 0;
205                while(s[l])
206                    l++;
207                append(s, l);
208            }
209        }
210        else if(f[0] == '0' && f[1] == '2' && f[2] == 'x')
211        {
212            int i = va_arg(args, int);
213            append(hex2char + ((i & 0xf0) >> 4), 1);
214            append(hex2char + (i & 0x0f), 1);
215            f += 2;
216        }
217        else
218        {
219            append(f - 1, 2);
220        }
221    }
222    append("\n", 1);
223
224    /* If the debug fd is open, we send the data */
225    if (_zz_debugfd >= 0)
226    {
227        write(_zz_debugfd, debugbuffer, debugcount);
228        debugcount = 0;
229    }
230
231    errno = saved_errno;
232}
233
Note: See TracBrowser for help on using the repository browser.