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

Revision 4231, 5.7 KB checked in by sam, 3 years ago (diff)

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

  • Property svn:keywords set to Id
RevLine 
[1470]1/*
2 *  zzuf - general purpose fuzzer
[4009]3 *  Copyright (c) 2006-2009 Sam Hocevar <sam@hocevar.net>
[1470]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>
[4151]27#include <string.h>
[1728]28#if defined HAVE_UNISTD_H
29#   include <unistd.h>
30#endif
[1730]31#if defined HAVE_IO_H
32#   include <io.h>
33#endif
[1470]34#include <errno.h>
35#include <stdarg.h>
36
37#include "debug.h"
[1535]38#include "libzzuf.h"
[1470]39
[4009]40static void mydebug(char const *format, va_list args);
[1504]41
[2336]42/**
43 * Helper macro to write an integer value to a given file descriptor,
44 * either in base 10 or in hexadecimal.
45 */
[4151]46#define WRITE_INT(i, base) \
[1578]47    do \
[1534]48    { \
[1578]49        char buf[128], *b = buf + 127; \
50        if(i <= 0) \
[4151]51            append((i = -i) ? "-" : "0", 1); /* XXX: hack here */ \
[1578]52        while(i) \
53        { \
54            *b-- = hex2char[i % base]; \
55            i /= base; \
56        } \
[4151]57        append(b + 1, (int)(buf + 127 - b)); \
[1578]58    } while(0)
[1534]59
[4151]60/* Temporary buffer for deferred output */
61char debugbuffer[BUFSIZ];
62size_t debugcount = 1;
63
[4009]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
[2336]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 */
[4151]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
[4009]102static void mydebug(char const *format, va_list args)
[1470]103{
[1534]104    static char const *hex2char = "0123456789abcdef";
105    char const *f;
[1718]106    int saved_errno;
[1470]107
108    saved_errno = errno;
[1735]109
[4151]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);
[1534]118    for(f = format; *f; f++)
119    {
120        if(*f != '%')
121        {
[4151]122            append(f, 1);
[1534]123            continue;
124        }
125
126        f++;
127        if(!*f)
128            break;
129
[1550]130        if(*f == 'c')
[1534]131        {
[1550]132            char i = (char)(unsigned char)va_arg(args, int);
[1636]133            if(i >= 0x20 && i < 0x7f)
[4151]134                append(&i, 1);
[1688]135            else if(i == '\n')
[4151]136                append("\\n", 2);
[1688]137            else if(i == '\t')
[4151]138                append("\\t", 2);
[1688]139            else if(i == '\r')
[4151]140                append("\\r", 2);
[1636]141            else
142            {
[4151]143                append("\\x", 2);
144                append(hex2char + ((i & 0xf0) >> 4), 1);
145                append(hex2char + (i & 0x0f), 1);
[1636]146            }
[1550]147        }
[1856]148        else if(*f == 'i' || *f == 'd')
[1550]149        {
[1534]150            int i = va_arg(args, int);
[4151]151            WRITE_INT(i, 10);
[1534]152        }
[1689]153        else if(*f == 'x')
154        {
155            int i = va_arg(args, int);
[4151]156            WRITE_INT(i, 16);
[1689]157        }
[1856]158        else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd'))
[1534]159        {
160            long int i = va_arg(args, long int);
[4151]161            WRITE_INT(i, 10);
[1534]162            f++;
163        }
[1856]164        else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd'))
[1534]165        {
166            long long int i = va_arg(args, long long int);
[4151]167            WRITE_INT(i, 10);
[1534]168            f += 2;
169        }
[2271]170        else if(f[0] == 'g')
171        {
172            double g = va_arg(args, double), h = 0.0000001;
[4100]173            int i = (int)g;
[4151]174            WRITE_INT(i, 10);
[2271]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)
[4151]182                    append(".", 1);
183                append(hex2char + (int)g, 1);
[2271]184            }
185        }
[1534]186        else if(f[0] == 'p')
187        {
188            uintptr_t i = va_arg(args, uintptr_t);
189            if(!i)
[4231]190                append("NULL", 4);
[1534]191            else
192            {
[4151]193                append("0x", 2);
194                WRITE_INT(i, 16);
[1534]195            }
196        }
197        else if(f[0] == 's')
198        {
199            char *s = va_arg(args, char *);
200            if(!s)
[4151]201                append("(nil)", 5);
[1534]202            else
203            {
204                int l = 0;
205                while(s[l])
206                    l++;
[4151]207                append(s, l);
[1534]208            }
209        }
210        else if(f[0] == '0' && f[1] == '2' && f[2] == 'x')
211        {
212            int i = va_arg(args, int);
[4151]213            append(hex2char + ((i & 0xf0) >> 4), 1);
214            append(hex2char + (i & 0x0f), 1);
[1534]215            f += 2;
216        }
217        else
218        {
[4151]219            append(f - 1, 2);
[1534]220        }
221    }
[4151]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
[1470]231    errno = saved_errno;
232}
[4151]233
Note: See TracBrowser for help on using the repository browser.