Coverage Report

Created: 2026-07-12 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mercurial/contrib/fuzz/manifest.cc
Line
Count
Source
1
#include <Python.h>
2
#include <assert.h>
3
#include <stdlib.h>
4
#include <unistd.h>
5
6
#include "FuzzedDataProvider.h"
7
#include "pyutil.h"
8
9
#include <string>
10
11
extern "C" {
12
13
static PYCODETYPE *code;
14
15
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
16
15
{
17
15
  contrib::initpy(*argv[0]);
18
15
  code = (PYCODETYPE *)Py_CompileString(R"py(
19
15
try:
20
15
  lm = parsers.lazymanifest(mdata)
21
15
  # iterate the whole thing, which causes the code to fully parse
22
15
  # every line in the manifest
23
15
  for e, _, _ in lm.iterentries():
24
15
      # also exercise __getitem__ et al
25
15
      lm[e]
26
15
      e in lm
27
15
      (e + 'nope') in lm
28
15
  lm[b'xyzzy'] = (b'\0' * nlen, 'x')
29
15
  # do an insert, text should change
30
15
  assert lm.text() != mdata, "insert should change text and didn't: %r %r" % (lm.text(), mdata)
31
15
  cloned = lm.filtercopy(lambda x: x != 'xyzzy')
32
15
  assert cloned.text() == mdata, 'cloned text should equal mdata'
33
15
  cloned.diff(lm)
34
15
  del lm[b'xyzzy']
35
15
  cloned.diff(lm)
36
15
  # should be back to the same
37
15
  assert lm.text() == mdata, "delete should have restored text but didn't: %r %r" % (lm.text(), mdata)
38
15
except Exception as e:
39
15
  pass
40
15
  # uncomment this print if you're editing this Python code
41
15
  # to debug failures.
42
15
  # print e
43
15
)py",
44
15
                                        "fuzzer", Py_file_input);
45
15
  return 0;
46
15
}
47
48
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
49
122
{
50
  // Don't allow fuzzer inputs larger than 100k, since we'll just bog
51
  // down and not accomplish much.
52
122
  if (Size > 100000) {
53
4
    return 0;
54
4
  }
55
118
  FuzzedDataProvider provider(Data, Size);
56
118
  Py_ssize_t nodelength = provider.ConsumeBool() ? 20 : 32;
57
118
  PyObject *nlen = PyLong_FromSsize_t(nodelength);
58
118
  PyObject *mtext =
59
118
      PyBytes_FromStringAndSize((const char *)Data, (Py_ssize_t)Size);
60
118
  PyObject *locals = PyDict_New();
61
118
  PyDict_SetItemString(locals, "mdata", mtext);
62
118
  PyDict_SetItemString(locals, "nlen", nlen);
63
118
  PyObject *res = PyEval_EvalCode(code, contrib::pyglobals(), locals);
64
118
  if (!res) {
65
0
    PyErr_Print();
66
0
  }
67
118
  Py_XDECREF(res);
68
118
  Py_DECREF(locals);
69
118
  Py_DECREF(mtext);
70
118
  return 0; // Non-zero return values are reserved for future use.
71
122
}
72
}