Coverage Report

Created: 2026-06-10 06:37

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