VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp@ 77482

Last change on this file since 77482 was 77482, checked in by vboxsync, 6 years ago

Runtime/fuzz: Rewriting the core fuzzed input generator.

The new implementation stores only changes between mutations and not the
complete input. This saves memory (at the cost of a bit of increased complexity
when generating the input) and allows to generate mutations when no initial corpus
data is available which is useful when trying to fuzz data streams like network connections.

There are two modes when creating a new fuzzing context:

  • BLOB is used for input data like files where an initial corpus is available
  • STREAM is used for data streams like network connections
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: fuzzclientcmd.cpp 77482 2019-02-27 13:17:24Z vboxsync $ */
2/** @file
3 * IPRT - Fuzzing framework API, fuzzed client command.
4 */
5
6/*
7 * Copyright (C) 2018-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/fuzz.h>
32#include "internal/iprt.h"
33
34#include <iprt/assert.h>
35#include <iprt/buildconfig.h>
36#include <iprt/errcore.h>
37#include <iprt/getopt.h>
38#include <iprt/mem.h>
39#include <iprt/message.h>
40#include <iprt/stream.h>
41#include <iprt/string.h>
42#include <iprt/types.h>
43#include <iprt/vfs.h>
44
45
46/**
47 * Fuzzing client command state.
48 */
49typedef struct RTFUZZCMDCLIENT
50{
51 /** Our own fuzzing context containing all the data. */
52 RTFUZZCTX hFuzzCtx;
53 /** Consumption callback. */
54 PFNFUZZCLIENTCONSUME pfnConsume;
55 /** Opaque user data to pass to the consumption callback. */
56 void *pvUser;
57 /** Standard input VFS handle. */
58 RTVFSIOSTREAM hVfsStdIn;
59 /** Standard output VFS handle. */
60 RTVFSIOSTREAM hVfsStdOut;
61} RTFUZZCMDCLIENT;
62/** Pointer to a fuzzing client command state. */
63typedef RTFUZZCMDCLIENT *PRTFUZZCMDCLIENT;
64
65
66/**
67 * The fuzzing client mainloop.
68 *
69 * @returns IPRT status code.
70 * @param pThis The fuzzing client command state.
71 */
72static int rtFuzzCmdClientMainloop(PRTFUZZCMDCLIENT pThis)
73{
74 int rc = VINF_SUCCESS;
75 bool fShutdown = false;
76
77 while ( !fShutdown
78 && RT_SUCCESS(rc))
79 {
80 RTFUZZINPUT hFuzzInput;
81
82 rc = RTFuzzCtxInputGenerate(pThis->hFuzzCtx, &hFuzzInput);
83 if (RT_SUCCESS(rc))
84 {
85 void *pv = NULL;
86 size_t cb = 0;
87 rc = RTFuzzInputQueryBlobData(hFuzzInput, &pv, &cb);
88 if (RT_SUCCESS(rc))
89 {
90 char bResp = '.';
91 int rc2 = pThis->pfnConsume(pv, cb, pThis->pvUser);
92 if (RT_SUCCESS(rc2))
93 {
94 rc = RTFuzzInputAddToCtxCorpus(hFuzzInput);
95 bResp = 'A';
96 }
97
98 if (RT_SUCCESS(rc))
99 rc = RTVfsIoStrmWrite(pThis->hVfsStdOut, &bResp, 1, true /*fBlocking*/, NULL);
100 }
101
102 RTFuzzInputRelease(hFuzzInput);
103 }
104 }
105
106 return rc;
107}
108
109
110/**
111 * Run the fuzzing client.
112 *
113 * @returns Process exit status.
114 * @param pThis The fuzzing client command state.
115 */
116static RTEXITCODE rtFuzzCmdClientRun(PRTFUZZCMDCLIENT pThis)
117{
118 int rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT, 0, true /*fLeaveOpen*/, &pThis->hVfsStdIn);
119 if (RT_SUCCESS(rc))
120 {
121 rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, 0, true /*fLeaveOpen*/, &pThis->hVfsStdOut);
122 if (RT_SUCCESS(rc))
123 {
124 /* Read the initial input fuzzer state from the standard input. */
125 uint32_t cbFuzzCtxState;
126 rc = RTVfsIoStrmRead(pThis->hVfsStdIn, &cbFuzzCtxState, sizeof(cbFuzzCtxState), true /*fBlocking*/, NULL);
127 if (RT_SUCCESS(rc))
128 {
129 void *pvFuzzCtxState = RTMemAllocZ(cbFuzzCtxState);
130 if (RT_LIKELY(pvFuzzCtxState))
131 {
132 rc = RTVfsIoStrmRead(pThis->hVfsStdIn, pvFuzzCtxState, cbFuzzCtxState, true /*fBlocking*/, NULL);
133 if (RT_SUCCESS(rc))
134 {
135 rc = RTFuzzCtxCreateFromState(&pThis->hFuzzCtx, pvFuzzCtxState, cbFuzzCtxState);
136 if (RT_SUCCESS(rc))
137 rc = rtFuzzCmdClientMainloop(pThis);
138 }
139
140 RTMemFree(pvFuzzCtxState);
141 }
142 else
143 rc = VERR_NO_MEMORY;
144 }
145 }
146 }
147
148 if (RT_SUCCESS(rc))
149 return RTEXITCODE_SUCCESS;
150
151 return RTEXITCODE_FAILURE;
152}
153
154
155RTR3DECL(RTEXITCODE) RTFuzzCmdFuzzingClient(unsigned cArgs, char **papszArgs, PFNFUZZCLIENTCONSUME pfnConsume, void *pvUser)
156{
157 /*
158 * Parse the command line.
159 */
160 static const RTGETOPTDEF s_aOptions[] =
161 {
162 { "--help", 'h', RTGETOPT_REQ_NOTHING },
163 { "--version", 'V', RTGETOPT_REQ_NOTHING },
164 };
165
166 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
167 RTGETOPTSTATE GetState;
168 int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
169 RTGETOPTINIT_FLAGS_OPTS_FIRST);
170 if (RT_SUCCESS(rc))
171 {
172 /* Option variables: */
173 RTFUZZCMDCLIENT This;
174
175 This.pfnConsume = pfnConsume;
176 This.pvUser = pvUser;
177
178 /* Argument parsing loop. */
179 bool fContinue = true;
180 do
181 {
182 RTGETOPTUNION ValueUnion;
183 int chOpt = RTGetOpt(&GetState, &ValueUnion);
184 switch (chOpt)
185 {
186 case 0:
187 fContinue = false;
188 break;
189
190 case 'h':
191 RTPrintf("Usage: to be written\nOption dump:\n");
192 for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
193 RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
194 fContinue = false;
195 break;
196
197 case 'V':
198 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
199 fContinue = false;
200 break;
201
202 default:
203 rcExit = RTGetOptPrintError(chOpt, &ValueUnion);
204 fContinue = false;
205 break;
206 }
207 } while (fContinue);
208
209 if (rcExit == RTEXITCODE_SUCCESS)
210 rcExit = rtFuzzCmdClientRun(&This);
211 }
212 else
213 rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "RTGetOptInit: %Rrc", rc);
214 return rcExit;
215}
216
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette