Coverage Report

Created: 2026-07-24 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tremor/ogg_fuzzer.cc
Line
Count
Source
1
/* Copyright 2026 Google LLC
2
3
Licensed under the Apache License, Version 2.0 (the "License");
4
you may not use this file except in compliance with the License.
5
You may obtain a copy of the License at
6
7
      http://www.apache.org/licenses/LICENSE-2.0
8
9
Unless required by applicable law or agreed to in writing, software
10
distributed under the License is distributed on an "AS IS" BASIS,
11
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
See the License for the specific language governing permissions and
13
limitations under the License.
14
*/
15
16
#include <stdint.h>
17
#include <string.h>
18
#include <stdlib.h>
19
#include <ogg/ogg.h>
20
21
1.14k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
22
1.14k
  if (size < 10) return 0;
23
24
  // Use the first few bytes to decide what to do
25
1.14k
  uint8_t action = data[0];
26
1.14k
  uint32_t serial = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
27
1.14k
  const uint8_t *fuzz_data = data + 5;
28
1.14k
  size_t fuzz_size = size - 5;
29
30
  // Fuzz ogg_sync and ogg_stream
31
1.14k
  ogg_sync_state oy;
32
1.14k
  ogg_stream_state os;
33
1.14k
  ogg_sync_init(&oy);
34
1.14k
  ogg_stream_init(&os, serial);
35
36
1.14k
  char *buf = ogg_sync_buffer(&oy, fuzz_size);
37
1.14k
  if (buf) {
38
1.14k
    memcpy(buf, fuzz_data, fuzz_size);
39
1.14k
    ogg_sync_wrote(&oy, fuzz_size);
40
1.14k
  }
41
42
1.14k
  ogg_page og;
43
7.17k
  while (ogg_sync_pageout(&oy, &og) == 1) {
44
6.03k
    ogg_stream_pagein(&os, &og);
45
6.03k
    ogg_packet op;
46
15.9k
    while (ogg_stream_packetout(&os, &op) == 1) {
47
      // Successfully extracted a packet
48
9.93k
    }
49
6.03k
  }
50
51
1.14k
  ogg_stream_clear(&os);
52
1.14k
  ogg_sync_clear(&oy);
53
54
  // Fuzz oggpack (bitwise) - LSb
55
1.14k
  oggpack_buffer opb;
56
1.14k
  oggpack_writeinit(&opb);
57
  
58
1.14k
  size_t pos = 0;
59
1.43M
  while (pos + 5 <= fuzz_size) {
60
1.43M
    uint8_t op_choice = fuzz_data[pos++];
61
1.43M
    uint32_t val = (fuzz_data[pos] << 24) | (fuzz_data[pos+1] << 16) | (fuzz_data[pos+2] << 8) | fuzz_data[pos+3];
62
1.43M
    pos += 4;
63
    
64
1.43M
    switch (op_choice % 4) {
65
1.41M
      case 0:
66
1.41M
        oggpack_write(&opb, val, fuzz_data[pos-1] % 33);
67
1.41M
        break;
68
6.16k
      case 1:
69
6.16k
        oggpack_writealign(&opb);
70
6.16k
        break;
71
763
      case 2:
72
763
        oggpack_writecopy(&opb, (void*)(fuzz_data + pos), (fuzz_size - pos) * 8);
73
763
        pos = fuzz_size; // consume rest
74
763
        break;
75
8.29k
      case 3:
76
8.29k
        oggpack_reset(&opb);
77
8.29k
        break;
78
1.43M
    }
79
1.43M
  }
80
  
81
  // Read back what we wrote
82
1.14k
  unsigned char *out_buf = oggpack_get_buffer(&opb);
83
1.14k
  long out_bytes = oggpack_bytes(&opb);
84
1.14k
  if (out_buf && out_bytes > 0) {
85
964
    oggpack_buffer opr;
86
964
    oggpack_readinit(&opr, out_buf, out_bytes);
87
10.6k
    for (int i = 0; i < 10; ++i) {
88
9.64k
        oggpack_look(&opr, 10);
89
9.64k
        oggpack_adv(&opr, 1);
90
9.64k
        oggpack_read(&opr, 8);
91
9.64k
    }
92
964
  }
93
1.14k
  oggpack_writeclear(&opb);
94
95
  // Fuzz oggpackB (bitwise) - MSb
96
1.14k
  oggpackB_writeinit(&opb);
97
1.14k
  pos = 0;
98
1.43M
  while (pos + 5 <= fuzz_size) {
99
1.43M
    uint8_t op_choice = fuzz_data[pos++];
100
1.43M
    uint32_t val = (fuzz_data[pos] << 24) | (fuzz_data[pos+1] << 16) | (fuzz_data[pos+2] << 8) | fuzz_data[pos+3];
101
1.43M
    pos += 4;
102
    
103
1.43M
    switch (op_choice % 4) {
104
1.41M
      case 0:
105
1.41M
        oggpackB_write(&opb, val, fuzz_data[pos-1] % 33);
106
1.41M
        break;
107
6.16k
      case 1:
108
6.16k
        oggpackB_writealign(&opb);
109
6.16k
        break;
110
763
      case 2:
111
763
        oggpackB_writecopy(&opb, (void*)(fuzz_data + pos), (fuzz_size - pos) * 8);
112
763
        pos = fuzz_size; // consume rest
113
763
        break;
114
8.29k
      case 3:
115
8.29k
        oggpackB_reset(&opb);
116
8.29k
        break;
117
1.43M
    }
118
1.43M
  }
119
1.14k
  out_buf = oggpackB_get_buffer(&opb);
120
1.14k
  out_bytes = oggpackB_bytes(&opb);
121
1.14k
  if (out_buf && out_bytes > 0) {
122
964
    oggpack_buffer opr;
123
964
    oggpackB_readinit(&opr, out_buf, out_bytes);
124
10.6k
    for (int i = 0; i < 10; ++i) {
125
9.64k
        oggpackB_look(&opr, 10);
126
9.64k
        oggpackB_adv(&opr, 1);
127
9.64k
        oggpackB_read(&opr, 8);
128
9.64k
    }
129
964
  }
130
1.14k
  oggpackB_writeclear(&opb);
131
132
1.14k
  return 0;
133
1.14k
}