Coverage Report

Created: 2026-09-01 07:19

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.13k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
22
1.13k
  if (size < 10) return 0;
23
24
  // Use the first few bytes to decide what to do
25
1.12k
  uint8_t action = data[0];
26
1.12k
  uint32_t serial = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
27
1.12k
  const uint8_t *fuzz_data = data + 5;
28
1.12k
  size_t fuzz_size = size - 5;
29
30
  // Fuzz ogg_sync and ogg_stream
31
1.12k
  ogg_sync_state oy;
32
1.12k
  ogg_stream_state os;
33
1.12k
  ogg_sync_init(&oy);
34
1.12k
  ogg_stream_init(&os, serial);
35
36
1.12k
  char *buf = ogg_sync_buffer(&oy, fuzz_size);
37
1.12k
  if (buf) {
38
1.12k
    memcpy(buf, fuzz_data, fuzz_size);
39
1.12k
    ogg_sync_wrote(&oy, fuzz_size);
40
1.12k
  }
41
42
1.12k
  ogg_page og;
43
6.98k
  while (ogg_sync_pageout(&oy, &og) == 1) {
44
5.85k
    ogg_stream_pagein(&os, &og);
45
5.85k
    ogg_packet op;
46
15.0k
    while (ogg_stream_packetout(&os, &op) == 1) {
47
      // Successfully extracted a packet
48
9.17k
    }
49
5.85k
  }
50
51
1.12k
  ogg_stream_clear(&os);
52
1.12k
  ogg_sync_clear(&oy);
53
54
  // Fuzz oggpack (bitwise) - LSb
55
1.12k
  oggpack_buffer opb;
56
1.12k
  oggpack_writeinit(&opb);
57
  
58
1.12k
  size_t pos = 0;
59
1.88M
  while (pos + 5 <= fuzz_size) {
60
1.88M
    uint8_t op_choice = fuzz_data[pos++];
61
1.88M
    uint32_t val = (fuzz_data[pos] << 24) | (fuzz_data[pos+1] << 16) | (fuzz_data[pos+2] << 8) | fuzz_data[pos+3];
62
1.88M
    pos += 4;
63
    
64
1.88M
    switch (op_choice % 4) {
65
1.87M
      case 0:
66
1.87M
        oggpack_write(&opb, val, fuzz_data[pos-1] % 33);
67
1.87M
        break;
68
2.43k
      case 1:
69
2.43k
        oggpack_writealign(&opb);
70
2.43k
        break;
71
741
      case 2:
72
741
        oggpack_writecopy(&opb, (void*)(fuzz_data + pos), (fuzz_size - pos) * 8);
73
741
        pos = fuzz_size; // consume rest
74
741
        break;
75
7.74k
      case 3:
76
7.74k
        oggpack_reset(&opb);
77
7.74k
        break;
78
1.88M
    }
79
1.88M
  }
80
  
81
  // Read back what we wrote
82
1.12k
  unsigned char *out_buf = oggpack_get_buffer(&opb);
83
1.12k
  long out_bytes = oggpack_bytes(&opb);
84
1.12k
  if (out_buf && out_bytes > 0) {
85
962
    oggpack_buffer opr;
86
962
    oggpack_readinit(&opr, out_buf, out_bytes);
87
10.5k
    for (int i = 0; i < 10; ++i) {
88
9.62k
        oggpack_look(&opr, 10);
89
9.62k
        oggpack_adv(&opr, 1);
90
9.62k
        oggpack_read(&opr, 8);
91
9.62k
    }
92
962
  }
93
1.12k
  oggpack_writeclear(&opb);
94
95
  // Fuzz oggpackB (bitwise) - MSb
96
1.12k
  oggpackB_writeinit(&opb);
97
1.12k
  pos = 0;
98
1.88M
  while (pos + 5 <= fuzz_size) {
99
1.88M
    uint8_t op_choice = fuzz_data[pos++];
100
1.88M
    uint32_t val = (fuzz_data[pos] << 24) | (fuzz_data[pos+1] << 16) | (fuzz_data[pos+2] << 8) | fuzz_data[pos+3];
101
1.88M
    pos += 4;
102
    
103
1.88M
    switch (op_choice % 4) {
104
1.87M
      case 0:
105
1.87M
        oggpackB_write(&opb, val, fuzz_data[pos-1] % 33);
106
1.87M
        break;
107
2.43k
      case 1:
108
2.43k
        oggpackB_writealign(&opb);
109
2.43k
        break;
110
741
      case 2:
111
741
        oggpackB_writecopy(&opb, (void*)(fuzz_data + pos), (fuzz_size - pos) * 8);
112
741
        pos = fuzz_size; // consume rest
113
741
        break;
114
7.74k
      case 3:
115
7.74k
        oggpackB_reset(&opb);
116
7.74k
        break;
117
1.88M
    }
118
1.88M
  }
119
1.12k
  out_buf = oggpackB_get_buffer(&opb);
120
1.12k
  out_bytes = oggpackB_bytes(&opb);
121
1.12k
  if (out_buf && out_bytes > 0) {
122
962
    oggpack_buffer opr;
123
962
    oggpackB_readinit(&opr, out_buf, out_bytes);
124
10.5k
    for (int i = 0; i < 10; ++i) {
125
9.62k
        oggpackB_look(&opr, 10);
126
9.62k
        oggpackB_adv(&opr, 1);
127
9.62k
        oggpackB_read(&opr, 8);
128
9.62k
    }
129
962
  }
130
1.12k
  oggpackB_writeclear(&opb);
131
132
1.12k
  return 0;
133
1.12k
}