VirtualBox

Ignore:
Timestamp:
Mar 5, 2019 10:30:33 AM (6 years ago)
Author:
vboxsync
Message:

Runtime/fuzz: Add libFuzzer compatible wrapper to be able to evaluate our fuzzer against others

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp

    r77509 r77564  
    3535#include <iprt/buildconfig.h>
    3636#include <iprt/errcore.h>
     37#include <iprt/file.h>
    3738#include <iprt/getopt.h>
     39#include <iprt/ldr.h>
    3840#include <iprt/mem.h>
    3941#include <iprt/message.h>
     
    4446
    4547
     48
     49typedef DECLCALLBACK(int) FNLLVMFUZZERTESTONEINPUT(const uint8_t *pbData, size_t cbData);
     50typedef FNLLVMFUZZERTESTONEINPUT *PFNLLVMFUZZERTESTONEINPUT;
     51
     52
    4653/**
    4754 * Fuzzing client command state.
     
    5057{
    5158    /** Our own fuzzing context containing all the data. */
    52     RTFUZZCTX               hFuzzCtx;
     59    RTFUZZCTX                 hFuzzCtx;
    5360    /** Consumption callback. */
    54     PFNFUZZCLIENTCONSUME    pfnConsume;
     61    PFNFUZZCLIENTCONSUME      pfnConsume;
    5562    /** Opaque user data to pass to the consumption callback. */
    56     void                    *pvUser;
     63    void                      *pvUser;
     64    /** The LLVM libFuzzer compatible entry point if configured */
     65    PFNLLVMFUZZERTESTONEINPUT pfnLlvmFuzzerTestOneInput;
     66    /** The selected input channel. */
     67    RTFUZZOBSINPUTCHAN        enmInputChan;
    5768    /** Standard input VFS handle. */
    58     RTVFSIOSTREAM           hVfsStdIn;
     69    RTVFSIOSTREAM             hVfsStdIn;
    5970    /** Standard output VFS handle. */
    60     RTVFSIOSTREAM           hVfsStdOut;
     71    RTVFSIOSTREAM             hVfsStdOut;
    6172} RTFUZZCMDCLIENT;
    6273/** Pointer to a fuzzing client command state. */
    6374typedef RTFUZZCMDCLIENT *PRTFUZZCMDCLIENT;
     75
     76
     77
     78/**
     79 * Runs the appropriate consumption callback with the provided data.
     80 *
     81 * @returns Status code, 0 for success.
     82 * @param   pThis               The fuzzing client command state.
     83 * @param   pvData              The data to consume.
     84 * @param   cbData              Size of the data in bytes.
     85 */
     86static int rtFuzzCmdClientConsume(PRTFUZZCMDCLIENT pThis, const void *pvData, size_t cbData)
     87{
     88    if (pThis->pfnLlvmFuzzerTestOneInput)
     89        return pThis->pfnLlvmFuzzerTestOneInput((const uint8_t *)pvData, cbData);
     90    else
     91        return pThis->pfnConsume(pvData, cbData, pThis->pvUser);
     92}
    6493
    6594
     
    89118            {
    90119                char bResp = '.';
    91                 int rc2 = pThis->pfnConsume(pv, cb, pThis->pvUser);
     120                int rc2 = rtFuzzCmdClientConsume(pThis, pv, cb);
    92121                if (RT_SUCCESS(rc2))
    93122                {
     
    153182
    154183
     184/**
     185 * Run a single iteration of the fuzzing client and return.
     186 *
     187 * @returns Process exit status.
     188 * @param   pThis               The fuzzing client command state.
     189 */
     190static RTEXITCODE rtFuzzCmdClientRunFile(PRTFUZZCMDCLIENT pThis, const char *pszFilename)
     191{
     192    void *pv = NULL;
     193    size_t cbFile = 0;
     194    int rc = RTFileReadAll(pszFilename, &pv, &cbFile);
     195    if (RT_SUCCESS(rc))
     196    {
     197        rtFuzzCmdClientConsume(pThis, pv, cbFile);
     198        RTFileReadAllFree(pv, cbFile);
     199        return RTEXITCODE_SUCCESS;
     200    }
     201
     202    return RTEXITCODE_FAILURE;
     203}
     204
     205
    155206RTR3DECL(RTEXITCODE) RTFuzzCmdFuzzingClient(unsigned cArgs, char **papszArgs, PFNFUZZCLIENTCONSUME pfnConsume, void *pvUser)
    156207{
     
    162213        { "--help",                            'h', RTGETOPT_REQ_NOTHING },
    163214        { "--version",                         'V', RTGETOPT_REQ_NOTHING },
     215        { "--llvm-input",                      'l', RTGETOPT_REQ_STRING  },
     216        { "--file",                            'f', RTGETOPT_REQ_STRING  },
    164217    };
    165218
     
    172225        /* Option variables:  */
    173226        RTFUZZCMDCLIENT This;
    174 
    175         This.pfnConsume = pfnConsume;
    176         This.pvUser     = pvUser;
     227        RTLDRMOD hLlvmMod = NIL_RTLDRMOD;
     228        const char *pszFilename = NULL;
     229
     230        This.pfnConsume   = pfnConsume;
     231        This.pvUser       = pvUser;
     232        This.enmInputChan = RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT;
    177233
    178234        /* Argument parsing loop. */
    179235        bool fContinue = true;
     236        bool fExit = false;
    180237        do
    181238        {
     
    188245                    break;
    189246
     247                case 'f':
     248                {
     249                    pszFilename = ValueUnion.psz;
     250                    This.enmInputChan = RTFUZZOBSINPUTCHAN_FILE;
     251                    break;
     252                }
     253
     254                case 'l':
     255                {
     256                    /*
     257                     * Load the indicated library and try to resolve LLVMFuzzerTestOneInput,
     258                     * which will act as the input callback.
     259                     */
     260                    rc = RTLdrLoad(ValueUnion.psz, &hLlvmMod);
     261                    if (RT_SUCCESS(rc))
     262                    {
     263                        rc = RTLdrGetSymbol(hLlvmMod, "LLVMFuzzerTestOneInput", (void **)&This.pfnLlvmFuzzerTestOneInput);
     264                        if (RT_FAILURE(rc))
     265                            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to query '%s' from '%s': %Rrc",
     266                                                    "LLVMFuzzerTestOneInput",
     267                                                    ValueUnion.psz,
     268                                                    rc);
     269                    }
     270                    break;
     271                }
     272
    190273                case 'h':
    191274                    RTPrintf("Usage: to be written\nOption dump:\n");
     
    193276                        RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
    194277                    fContinue = false;
     278                    fExit = true;
    195279                    break;
    196280
     
    198282                    RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
    199283                    fContinue = false;
     284                    fExit = true;
    200285                    break;
    201286
     
    207292        } while (fContinue);
    208293
    209         if (rcExit == RTEXITCODE_SUCCESS)
    210             rcExit = rtFuzzCmdClientRun(&This);
     294        if (   rcExit == RTEXITCODE_SUCCESS
     295            && !fExit)
     296        {
     297            switch (This.enmInputChan)
     298            {
     299                case RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT:
     300                    rcExit = rtFuzzCmdClientRun(&This);
     301                    break;
     302                case RTFUZZOBSINPUTCHAN_FILE:
     303                    rcExit = rtFuzzCmdClientRunFile(&This, pszFilename);
     304                    break;
     305                default:
     306                    rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "Input channel unknown/not implemented yet");
     307            }
     308        }
     309
     310        if (hLlvmMod != NIL_RTLDRMOD)
     311            RTLdrClose(hLlvmMod);
    211312    }
    212313    else
Note: See TracChangeset for help on using the changeset viewer.

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