Coverage Report

Created: 2026-09-01 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-json/fuzz-istream-json-string.c
Line
Count
Source
1
/* Copyright (c) Dovecot authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "str.h"
5
#include "istream.h"
6
#include "istream-private.h"
7
#include "test-common.h"
8
#include "fuzzer.h"
9
10
#include "istream-json-string.h"
11
12
/*
13
 * Feed arbitrary bytes into i_stream_create_json_string() and:
14
 *   1. Drain the decoded output completely.
15
 *   2. If the stream is seekable, seek back to 0 and drain again,
16
 *      verifying both reads produce identical output.
17
 */
18
1.96k
FUZZ_BEGIN_DATA(const unsigned char *data, size_t size)
19
1.96k
{
20
1.96k
  struct istream *raw, *jstr;
21
1.96k
  const unsigned char *buf;
22
1.96k
  size_t buf_size;
23
1.96k
  string_t *first, *second;
24
1.96k
  ssize_t ret;
25
26
1.96k
  raw = i_stream_create_from_data(data, size);
27
1.96k
  jstr = i_stream_create_json_string(raw);
28
1.96k
  i_stream_unref(&raw);
29
30
  /* First pass: decode everything */
31
1.96k
  first = str_new(default_pool, 64);
32
7.09k
  while ((ret = i_stream_read_more(jstr, &buf, &buf_size)) > 0) {
33
6.11k
    str_append_data(first, buf, buf_size);
34
6.11k
    i_stream_skip(jstr, buf_size);
35
6.11k
  }
36
  /* ret == -1 on EOF or error; either is acceptable for fuzz input */
37
38
  /* Second pass: seek back and verify output is identical.
39
     Only meaningful when the first pass completed without error;
40
     i_stream_seek() is a no-op when stream_errno != 0. */
41
1.96k
  if (jstr->seekable && jstr->stream_errno == 0) {
42
571
    i_stream_seek(jstr, 0);
43
44
571
    second = str_new(default_pool, 64);
45
6.53k
    while ((ret = i_stream_read_more(jstr, &buf, &buf_size)) > 0) {
46
5.96k
      str_append_data(second, buf, buf_size);
47
5.96k
      i_stream_skip(jstr, buf_size);
48
5.96k
    }
49
50
    /* Both reads must produce the same bytes */
51
571
    i_assert(str_len(first) == str_len(second) &&
52
571
       memcmp(str_data(first), str_data(second),
53
571
        str_len(first)) == 0);
54
571
    str_free(&second);
55
571
  }
56
57
981
  str_free(&first);
58
981
  i_stream_unref(&jstr);
59
981
}
60
981
FUZZ_END