contrib/fuzz/mpatch.cc
author Pierre-Yves David <pierre-yves.david@octobus.net>
Fri, 08 Nov 2019 14:00:22 +0100
changeset 43537 7f489b9a79a1
parent 38246 46dcb9f14900
child 43809 51a99e09c54b
permissions -rw-r--r--
index: use `index.has_node` in `repo._rollback` Differential Revision: https://phab.mercurial-scm.org/D7329
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38246
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     1
/*
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     2
 * mpatch.cc - fuzzer harness for mpatch.c
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     3
 *
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     4
 * Copyright 2018, Google Inc.
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     5
 *
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     6
 * This software may be used and distributed according to the terms of
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     7
 * the GNU General Public License, incorporated herein by reference.
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     8
 */
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
     9
#include <iostream>
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    10
#include <memory>
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    11
#include <stdint.h>
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    12
#include <stdlib.h>
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    13
#include <vector>
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    14
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    15
#include "fuzzutil.h"
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    16
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    17
// To avoid having too many OOMs from the fuzzer infrastructure, we'll
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    18
// skip patch application if the resulting fulltext would be bigger
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    19
// than 10MiB.
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    20
#define MAX_OUTPUT_SIZE 10485760
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    21
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    22
extern "C" {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    23
#include "bitmanipulation.h"
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    24
#include "mpatch.h"
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    25
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    26
struct mpatchbin {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    27
	std::unique_ptr<char[]> data;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    28
	size_t len;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    29
};
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    30
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    31
static mpatch_flist *getitem(void *vbins, ssize_t pos)
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    32
{
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    33
	std::vector<mpatchbin> *bins = (std::vector<mpatchbin> *)vbins;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    34
	const mpatchbin &bin = bins->at(pos + 1);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    35
	struct mpatch_flist *res;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    36
	LOG(2) << "mpatch_decode " << bin.len << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    37
	if (mpatch_decode(bin.data.get(), bin.len, &res) < 0)
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    38
		return NULL;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    39
	return res;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    40
}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    41
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    42
// input format:
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    43
// u8 number of inputs
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    44
// one u16 for each input, its length
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    45
// the inputs
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    46
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    47
{
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    48
	if (!Size) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    49
		return 0;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    50
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    51
	// First byte of data is how many texts we expect, first text
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    52
	// being the base the rest being the deltas.
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    53
	ssize_t numtexts = Data[0];
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    54
	if (numtexts < 2) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    55
		// No point if we don't have at least a base text and a delta...
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    56
		return 0;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    57
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    58
	// Each text will be described by a byte for how long it
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    59
	// should be, so give up if we don't have enough.
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    60
	if ((Size - 1) < (numtexts * 2)) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    61
		return 0;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    62
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    63
	size_t consumed = 1 + (numtexts * 2);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    64
	LOG(2) << "input contains " << Size << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    65
	LOG(2) << numtexts << " texts, consuming " << consumed << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    66
	std::vector<mpatchbin> bins;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    67
	bins.reserve(numtexts);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    68
	for (int i = 0; i < numtexts; ++i) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    69
		mpatchbin bin;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    70
		size_t nthsize = getbeuint16((char *)Data + 1 + (2 * i));
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    71
		LOG(2) << "text " << i << " is " << nthsize << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    72
		char *start = (char *)Data + consumed;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    73
		consumed += nthsize;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    74
		if (consumed > Size) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    75
			LOG(2) << "ran out of data, consumed " << consumed
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    76
			       << " of " << Size << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    77
			return 0;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    78
		}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    79
		bin.len = nthsize;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    80
		bin.data.reset(new char[nthsize]);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    81
		memcpy(bin.data.get(), start, nthsize);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    82
		bins.push_back(std::move(bin));
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    83
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    84
	LOG(2) << "mpatch_flist" << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    85
	struct mpatch_flist *patch =
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    86
	    mpatch_fold(&bins, getitem, 0, numtexts - 1);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    87
	if (!patch) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    88
		return 0;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    89
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    90
	LOG(2) << "mpatch_calcsize" << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    91
	ssize_t outlen = mpatch_calcsize(bins[0].len, patch);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    92
	LOG(2) << "outlen " << outlen << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    93
	if (outlen < 0 || outlen > MAX_OUTPUT_SIZE) {
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    94
		goto cleanup;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    95
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    96
	{
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    97
		char *dest = (char *)malloc(outlen);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    98
		LOG(2) << "expecting " << outlen << " total bytes at "
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
    99
		       << (void *)dest << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   100
		mpatch_apply(dest, bins[0].data.get(), bins[0].len, patch);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   101
		free(dest);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   102
		LOG(1) << "applied a complete patch" << std::endl;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   103
	}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   104
cleanup:
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   105
	mpatch_lfree(patch);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   106
	return 0;
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   107
}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   108
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   109
#ifdef HG_FUZZER_INCLUDE_MAIN
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   110
int main(int argc, char **argv)
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   111
{
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   112
	// One text, one patch.
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   113
	const char data[] = "\x02\x00\0x1\x00\x0d"
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   114
	                    // base text
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   115
	                    "a"
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   116
	                    // binary delta that will append a single b
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   117
	                    "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01b";
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   118
	return LLVMFuzzerTestOneInput((const uint8_t *)data, 19);
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   119
}
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   120
#endif
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   121
46dcb9f14900 fuzz: new fuzzer for the mpatch code
Augie Fackler <augie@google.com>
parents:
diff changeset
   122
} // extern "C"