contrib/fuzz/mpatch.cc
author Gregory Szorc <gregory.szorc@gmail.com>
Mon, 10 Dec 2018 18:04:12 +0000
changeset 40923 3ed77780f4a6
parent 38246 46dcb9f14900
child 43809 51a99e09c54b
permissions -rw-r--r--
wireprotov2: send linknodes to emitfilerevisions() Previously, linknodes were calculated within emitfilerevisions() by using filectx.introrev(), which would always use the linkrev/linknode as recorded by storage. This is wrong for cases where the receiver doesn't have the changeset the linknode refers to. This commit changes the logic for linknode emission so the mapping of filenode to linknode is computed by the caller and passed into emitfilerevisions(). As part of the change, linknodes for "filesdata" in the haveparents=False case are now correct: the existing code performed a manifest walk and it was trivial to plug in the correct linknode. However, behavior for the haveparents=True case is still wrong because it relies on filtering linkrevs against the outgoing set in order to determine what to send. This will be fixed in a subsequent commit. The change test test-wireproto-exchangev2-shallow.t is a bit wonky. The test repo has 6 revisions. The changed test is performing a shallow clone with depth=1. So, only file data for revision 5 is present locally. So, the new behavior of associating the linknode with revision 5 for every file revision seems correct. Of course, when backfilling old revisions, we'll want to update the linknode. But this problem requires wire protocol support and we'll cross that bridge later. Differential Revision: https://phab.mercurial-scm.org/D5405
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"