Changeset 4827 for zzuf


Ignore:
Timestamp:
Jul 11, 2012, 3:01:20 PM (7 years ago)
Author:
wisk
Message:

on win32, use a named pipe and IOCP to read stdout, stderr and debugfd correctly.

Location:
zzuf/trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/libzzuf/debug.c

    r4673 r4827  
    6666size_t debugcount = 1;
    6767
     68#ifdef _WIN32
     69
     70CRITICAL_SECTION _zz_pipe_cs; /* Initialized in DllMain */
     71
     72void _zz_debug(char const *format, ...)
     73{
     74    va_list args;
     75    char buf[0x100];
     76    DWORD written;
     77    va_start(args, format);
     78    //if (_zz_debuglevel >= 1) // LATER:
     79    {
     80        HANDLE dbg_hdl = (HANDLE)_get_osfhandle(_zz_debugfd);
     81        int ret = _vsnprintf(buf, sizeof(buf), format, args);
     82
     83        if (ret <= 0)       return;  /* if _snprintf failed, we send nothing                    */
     84        if (buf[0] == '\0') return; /* if the buf is empty, we don't bother to send it to zzuf */
     85
     86        /* FIXME: if len >= count, no null-terminator is appended, so we may erased the last character */
     87        if (ret >= sizeof(buf)) buf[ret - 1] = '\n';
     88        else                    buf[ret++]   = '\n';
     89
     90        EnterCriticalSection(&_zz_pipe_cs);
     91        WriteFile(dbg_hdl, buf, ret, &written, NULL);
     92        LeaveCriticalSection(&_zz_pipe_cs);
     93    }
     94    va_end(args);
     95    fflush(NULL); /* flush all streams to make sure zzuf gotta catch 'em all */
     96}
     97
     98void _zz_debug2(char const *format, ...)
     99{
     100    va_list args;
     101    char buf[0x100];
     102    DWORD written;
     103    va_start(args, format);
     104    //if (_zz_debuglevel >= 1) // LATER:
     105    {
     106        HANDLE dbg_hdl = (HANDLE)_get_osfhandle(_zz_debugfd);
     107        int ret = _vsnprintf(buf, sizeof(buf), format, args);
     108
     109        if (ret <= 0)       return;  /* if _snprintf failed, we send nothing                    */
     110        if (buf[0] == '\0') return; /* if the buf is empty, we don't bother to send it to zzuf */
     111
     112        /* FIXME: if len >= count, no null-terminator is appended, so we may erased the last character */
     113        if (ret >= sizeof(buf)) buf[ret - 1] = '\n';
     114        else                    buf[ret++]   = '\n';
     115
     116        EnterCriticalSection(&_zz_pipe_cs);
     117        WriteFile(dbg_hdl, buf, ret, &written, NULL);
     118        LeaveCriticalSection(&_zz_pipe_cs);
     119    }
     120    va_end(args);
     121    fflush(NULL); /* flush all streams to make sure zzuf gotta catch 'em all */
     122}
     123#else
    68124void _zz_debug(char const *format, ...)
    69125{
     
    83139    va_end(args);
    84140}
     141#endif
    85142
    86143/**
  • zzuf/trunk/src/libzzuf/lib-win32.c

    r4826 r4827  
    123123           LPOVERLAPPED lpOverlapped)
    124124{
    125     return ORIG(ReadFile)(hFile, lpBuffer, nNumberOfBytesToRead,
     125    BOOL ret;
     126    ret = ORIG(ReadFile)(hFile, lpBuffer, nNumberOfBytesToRead,
    126127                          lpNumberOfBytesRead, lpOverlapped);
     128    debug("ReadFile(%#08x, %#08x, %#08x, %#08x, %#08x) = %s",
     129        hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped, (ret ? "TRUE" : "FALSE"));
     130    return ret;
    127131}
    128132#endif
     
    137141    BOOL ret;
    138142    ret = ORIG(CloseHandle)(hObject);
    139     debug("CloseHandle(%i) = %i", (int)hObject, ret);
     143    debug("CloseHandle(%i) = %s", (int)hObject, (ret ? "TRUE" : "FALSE"));
    140144    return ret;
    141145}
  • zzuf/trunk/src/libzzuf/libzzuf.c

    r4676 r4827  
    230230    {
    231231        case DLL_PROCESS_ATTACH:
     232            InitializeCriticalSection(&_zz_pipe_cs);
    232233            _zz_init();
    233234            break;
    234235        case DLL_PROCESS_DETACH:
    235236            _zz_fini();
     237            DeleteCriticalSection(&_zz_pipe_cs);
    236238            break;
    237239    }
  • zzuf/trunk/src/libzzuf/libzzuf.h

    r4258 r4827  
    3737extern void _zz_mem_init(void);
    3838
     39#ifdef _WIN32
     40#   include <Windows.h>
     41extern CRITICAL_SECTION _zz_pipe_cs;
     42#endif
  • zzuf/trunk/src/myfork.c

    r4826 r4827  
    9393#if defined HAVE_PIPE
    9494        ret = pipe(pipes[i]);
    95 #elif defined HAVE__PIPE
     95#elif defined HAVE__PIPE && !defined _WIN32
    9696        int tmp;
    9797        /* The pipe is created with NOINHERIT otherwise both parts are
     
    101101        close(pipes[i][1]);
    102102        pipes[i][1] = tmp;
     103#elif defined _WIN32
     104        // http://www.daniweb.com/software-development/cpp/threads/295780/using-named-pipes-with-asynchronous-io-redirection-to-winapi
     105        {
     106            static int pipe_cnt = 0;
     107            char pipe_name[BUFSIZ];
     108            HANDLE pipe_hdl[2];         /* [0] read | [1] write */
     109            HANDLE new_hdl;
     110            SECURITY_ATTRIBUTES sa;
     111            sa.nLength              = sizeof(sa);
     112            sa.bInheritHandle       = TRUE;
     113            sa.lpSecurityDescriptor = NULL;
     114
     115            ret = 0;
     116
     117            /* Since we have to use a named pipe, we have to make sure the name is unique */
     118            _snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\Pipe\\zzuf.%08x.%d", GetCurrentProcessId(), pipe_cnt++);
     119
     120            /* At this time, the HANDLE is inheritable and can both read/write */
     121            if ((pipe_hdl[0] = CreateNamedPipeA(
     122                pipe_name,
     123                PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
     124                PIPE_TYPE_BYTE | PIPE_WAIT,
     125                1,
     126                BUFSIZ,
     127                BUFSIZ,
     128                0,
     129                &sa)) == INVALID_HANDLE_VALUE ||
     130
     131            /* Create a new handle for writing access only and it must be inheritable */
     132            (pipe_hdl[1] = CreateFileA(
     133                pipe_name,
     134                GENERIC_WRITE,
     135                0,
     136                &sa,
     137                OPEN_EXISTING,
     138                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
     139                NULL)) == INVALID_HANDLE_VALUE)
     140                ret = -1;
     141
     142            /* Now we create a new handle for the listener which is not inheritable */
     143            if (!DuplicateHandle(
     144                GetCurrentProcess(), pipe_hdl[0],
     145                GetCurrentProcess(), &new_hdl,
     146                0, FALSE,
     147                DUPLICATE_SAME_ACCESS))
     148                ret = -1;
     149
     150            /* Finally we can safetly close the pipe handle */
     151            CloseHandle(pipe_hdl[0]);
     152
     153            /* Now we convert handle to fd */
     154            pipes[i][0] = _open_osfhandle((intptr_t)new_hdl,     0x0);
     155            pipes[i][1] = _open_osfhandle((intptr_t)pipe_hdl[1], 0x0);
     156        }
    103157#endif
    104158        if(ret < 0)
  • zzuf/trunk/src/zzuf.c

    r4683 r4827  
    113113    ((fd >= 0) && (FD_ISSET(fd, p_fdset)))
    114114
     115#if defined _WIN32
     116#   include <Windows.h>
     117static CRITICAL_SECTION _zz_pipe_cs;
     118#endif
     119
    115120int main(int argc, char *argv[])
    116121{
     
    123128    int debug = 0, network = 0;
    124129    int i;
     130
     131#if defined _WIN32
     132    InitializeCriticalSection(&_zz_pipe_cs);
     133#endif
    125134
    126135    _zz_opts_init(opts);
     
    537546    _zz_opts_fini(opts);
    538547
     548#if defined _WIN32
     549    DeleteCriticalSection(&_zz_pipe_cs);
     550#endif
     551
    539552    return opts->crashes ? EXIT_FAILURE : EXIT_SUCCESS;
    540553}
     
    915928}
    916929
     930#ifdef _WIN32
     931
     932/* This structure contains useful information about data sent from fuzzed applications */
     933struct child_overlapped
     934{
     935    OVERLAPPED overlapped;
     936    char buf[BUFSIZ];
     937    struct opts * opts;
     938    int child_no;
     939    int fd_no;
     940};
     941
     942/* This callback is called when fuzzed applications write in fd out, err or debug */
     943static void _stdcall read_child(DWORD err_code, DWORD nbr_of_bytes_transfered, LPOVERLAPPED overlapped)
     944{
     945    struct child_overlapped * co = (struct child_overlapped *)overlapped;
     946
     947    /* TODO: handle more cases like ERROR_MORE_DATA */
     948    if (err_code != ERROR_SUCCESS) return;
     949
     950    EnterCriticalSection(&_zz_pipe_cs);
     951    switch (co->fd_no)
     952    {
     953    case 0: /* debug fd */
     954        write(1, "dbg: ", 4);
     955    case 1: /* out */
     956        write(1, co->buf, nbr_of_bytes_transfered); break;
     957    case 2: /* err */
     958        write(2, co->buf, nbr_of_bytes_transfered); break;
     959    default: break;
     960    }
     961    LeaveCriticalSection(&_zz_pipe_cs);
     962
     963    if(co->fd_no != 0) /* either out or err fd */
     964        co->opts->child[co->child_no].bytes += nbr_of_bytes_transfered;
     965
     966    if(co->opts->md5 && co->fd_no == 2)
     967        _zz_md5_add(co->opts->child[co->child_no].ctx, co->buf, nbr_of_bytes_transfered);
     968
     969    free(co); /* clean up allocated data */
     970}
     971
     972/* Since on windows select doesn't support file HANDLE, we use IOCP */
     973static void read_children(struct opts *opts)
     974{
     975    size_t i, j;
     976    HANDLE *children_handle, * cur_child_handle;
     977    size_t fd_number = opts->maxchild * 3;
     978
     979    cur_child_handle = children_handle = malloc(sizeof(*children_handle) * fd_number);
     980
     981    for(i = 0; i < fd_number; i++)
     982        children_handle[i] = INVALID_HANDLE_VALUE;
     983
     984    /* XXX: cute (i, j) iterating hack */
     985    for(i = 0, j = 0; i < (size_t)opts->maxchild; i += (j == 2), j = (j + 1) % 3)
     986    {
     987        struct child_overlapped * co;
     988        HANDLE h;
     989
     990        if(opts->child[i].status != STATUS_RUNNING)
     991            continue;
     992
     993        co = malloc(sizeof(*co));
     994        ZeroMemory(co, sizeof(*co));
     995        *cur_child_handle = co->overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
     996        co->child_no = i;
     997        co->fd_no    = j;
     998        co->opts     = opts;
     999
     1000        h = (HANDLE)_get_osfhandle(opts->child[i].fd[j]);
     1001
     1002        /* FIXME: handle error */
     1003        ReadFileEx(h, co->buf, sizeof(co->buf), (LPOVERLAPPED)co, read_child);
     1004        cur_child_handle++;
     1005    }
     1006
     1007    /* FIXME: handle error */
     1008    WaitForMultipleObjectsEx(fd_number, children_handle, FALSE, INFINITE, TRUE);
     1009}
     1010
     1011#else
    9171012static void read_children(struct opts *opts)
    9181013{
     
    9341029    tv.tv_usec = 1000;
    9351030
    936 #if !defined _WIN32
    937     /* Win32 does not support select() on non-sockets */
    9381031    errno = 0;
    9391032    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
     
    9421035    if(ret <= 0)
    9431036        return;
    944 #endif
    9451037
    9461038    /* XXX: cute (i, j) iterating hack */
     
    9521044            continue;
    9531045
    954 #if !defined _WIN32
    9551046        if(!ZZUF_FD_ISSET(opts->child[i].fd[j], &fdset))
    9561047            continue;
    957 #endif
    9581048
    9591049        ret = read(opts->child[i].fd[j], buf, BUFSIZ - 1);
     
    9691059                write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret);
    9701060        }
    971 #if !defined _WIN32
    9721061        else if(ret == 0)
    9731062        {
     
    9811070                opts->child[i].status = STATUS_EOF;
    9821071        }
    983 #endif
    984     }
    985 }
     1072    }
     1073}
     1074#endif
    9861075
    9871076#if !defined HAVE_SETENV
Note: See TracChangeset for help on using the changeset viewer.