Coverage Report

Created: 2026-02-14 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wuffs/fuzz/c/fuzzlib/fuzzlib_image_decoder.c
Line
Count
Source
1
// Copyright 2020 The Wuffs Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8
//
9
// SPDX-License-Identifier: Apache-2.0 OR MIT
10
11
#ifndef WUFFS_INCLUDE_GUARD
12
#error "Wuffs' .h files need to be included before this file"
13
#endif
14
15
static const char*  //
16
fuzz_image_decoder(wuffs_base__io_buffer* src,
17
                   uint64_t hash,
18
14.8k
                   wuffs_base__image_decoder* dec) {
19
14.8k
  const char* ret = NULL;
20
14.8k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
14.8k
  wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
22
23
  // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
24
  // variable initialization" warnings.
25
14.8k
  {
26
14.8k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
14.8k
    wuffs_base__status status =
28
14.8k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
14.8k
    if (!wuffs_base__status__is_ok(&status)) {
30
4.70k
      ret = wuffs_base__status__message(&status);
31
4.70k
      goto exit;
32
4.70k
    }
33
10.1k
    if (!wuffs_base__image_config__is_valid(&ic)) {
34
0
      ret = "invalid image_config";
35
0
      goto exit;
36
0
    }
37
38
    // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
39
10.1k
    if (hash & 1) {
40
5.64k
      wuffs_base__pixel_config__set(
41
5.64k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
5.64k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
5.64k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
5.64k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
5.64k
    }
46
10.1k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
10.1k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
10.1k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
28
      ret = "image too large";
53
28
      goto exit;
54
28
    }
55
10.1k
    if (n > 0) {
56
6.00k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
6.00k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
6.00k
    }
62
63
10.1k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
10.1k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
138
      ret = "image too large";
66
138
      goto exit;
67
138
    }
68
10.0k
    if (n > 0) {
69
9.83k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
9.83k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
9.83k
    }
75
76
10.0k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
10.0k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
10.0k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
10.0k
    bool seen_ok = false;
84
266k
    while (true) {
85
266k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
266k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
266k
      if (!wuffs_base__status__is_ok(&status)) {
88
901
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
635
          ret = wuffs_base__status__message(&status);
90
635
        }
91
901
        goto exit;
92
901
      }
93
94
265k
      status = wuffs_base__image_decoder__decode_frame(
95
265k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
265k
      wuffs_base__rect_ie_u32 frame_rect =
98
265k
          wuffs_base__frame_config__bounds(&fc);
99
265k
      wuffs_base__rect_ie_u32 dirty_rect =
100
265k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
265k
      if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
102
0
        ret = "internal error: frame_rect does not contain dirty_rect";
103
0
        goto exit;
104
0
      }
105
106
265k
      if (!wuffs_base__status__is_ok(&status)) {
107
9.13k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
9.13k
          ret = wuffs_base__status__message(&status);
109
9.13k
        }
110
9.13k
        goto exit;
111
9.13k
      }
112
256k
      seen_ok = true;
113
114
256k
      if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
115
0
        ret = "internal error: frame_rect does not equal dirty_rect";
116
0
        goto exit;
117
0
      }
118
256k
    }
119
10.0k
  }
120
121
14.8k
exit:
122
14.8k
  free(workbuf.ptr);
123
14.8k
  free(pixbuf.ptr);
124
14.8k
  return ret;
125
10.0k
}
png_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
5.05k
                   wuffs_base__image_decoder* dec) {
19
5.05k
  const char* ret = NULL;
20
5.05k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
5.05k
  wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
22
23
  // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
24
  // variable initialization" warnings.
25
5.05k
  {
26
5.05k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
5.05k
    wuffs_base__status status =
28
5.05k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
5.05k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.44k
      ret = wuffs_base__status__message(&status);
31
1.44k
      goto exit;
32
1.44k
    }
33
3.60k
    if (!wuffs_base__image_config__is_valid(&ic)) {
34
0
      ret = "invalid image_config";
35
0
      goto exit;
36
0
    }
37
38
    // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
39
3.60k
    if (hash & 1) {
40
1.82k
      wuffs_base__pixel_config__set(
41
1.82k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.82k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.82k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.82k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.82k
    }
46
3.60k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
3.60k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
3.60k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
8
      ret = "image too large";
53
8
      goto exit;
54
8
    }
55
3.60k
    if (n > 0) {
56
3.60k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
3.60k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
3.60k
    }
62
63
3.60k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
3.60k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
1
      ret = "image too large";
66
1
      goto exit;
67
1
    }
68
3.60k
    if (n > 0) {
69
3.60k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
3.60k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
3.60k
    }
75
76
3.60k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
3.60k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
3.60k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
3.60k
    bool seen_ok = false;
84
5.59k
    while (true) {
85
5.59k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
5.59k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
5.59k
      if (!wuffs_base__status__is_ok(&status)) {
88
361
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
345
          ret = wuffs_base__status__message(&status);
90
345
        }
91
361
        goto exit;
92
361
      }
93
94
5.23k
      status = wuffs_base__image_decoder__decode_frame(
95
5.23k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
5.23k
      wuffs_base__rect_ie_u32 frame_rect =
98
5.23k
          wuffs_base__frame_config__bounds(&fc);
99
5.23k
      wuffs_base__rect_ie_u32 dirty_rect =
100
5.23k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
5.23k
      if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
102
0
        ret = "internal error: frame_rect does not contain dirty_rect";
103
0
        goto exit;
104
0
      }
105
106
5.23k
      if (!wuffs_base__status__is_ok(&status)) {
107
3.23k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
3.23k
          ret = wuffs_base__status__message(&status);
109
3.23k
        }
110
3.23k
        goto exit;
111
3.23k
      }
112
1.99k
      seen_ok = true;
113
114
1.99k
      if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
115
0
        ret = "internal error: frame_rect does not equal dirty_rect";
116
0
        goto exit;
117
0
      }
118
1.99k
    }
119
3.60k
  }
120
121
5.05k
exit:
122
5.05k
  free(workbuf.ptr);
123
5.05k
  free(pixbuf.ptr);
124
5.05k
  return ret;
125
3.60k
}
gif_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
2.22k
                   wuffs_base__image_decoder* dec) {
19
2.22k
  const char* ret = NULL;
20
2.22k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
2.22k
  wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
22
23
  // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
24
  // variable initialization" warnings.
25
2.22k
  {
26
2.22k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
2.22k
    wuffs_base__status status =
28
2.22k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
2.22k
    if (!wuffs_base__status__is_ok(&status)) {
30
692
      ret = wuffs_base__status__message(&status);
31
692
      goto exit;
32
692
    }
33
1.53k
    if (!wuffs_base__image_config__is_valid(&ic)) {
34
0
      ret = "invalid image_config";
35
0
      goto exit;
36
0
    }
37
38
    // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
39
1.53k
    if (hash & 1) {
40
758
      wuffs_base__pixel_config__set(
41
758
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
758
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
758
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
758
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
758
    }
46
1.53k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
1.53k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
1.53k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
0
      ret = "image too large";
53
0
      goto exit;
54
0
    }
55
1.53k
    if (n > 0) {
56
0
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
0
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
0
    }
62
63
1.53k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
1.53k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
60
      ret = "image too large";
66
60
      goto exit;
67
60
    }
68
1.47k
    if (n > 0) {
69
1.31k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
1.31k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
1.31k
    }
75
76
1.47k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
1.47k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
1.47k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
1.47k
    bool seen_ok = false;
84
255k
    while (true) {
85
255k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
255k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
255k
      if (!wuffs_base__status__is_ok(&status)) {
88
359
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
290
          ret = wuffs_base__status__message(&status);
90
290
        }
91
359
        goto exit;
92
359
      }
93
94
255k
      status = wuffs_base__image_decoder__decode_frame(
95
255k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
255k
      wuffs_base__rect_ie_u32 frame_rect =
98
255k
          wuffs_base__frame_config__bounds(&fc);
99
255k
      wuffs_base__rect_ie_u32 dirty_rect =
100
255k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
255k
      if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
102
0
        ret = "internal error: frame_rect does not contain dirty_rect";
103
0
        goto exit;
104
0
      }
105
106
255k
      if (!wuffs_base__status__is_ok(&status)) {
107
1.11k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
1.11k
          ret = wuffs_base__status__message(&status);
109
1.11k
        }
110
1.11k
        goto exit;
111
1.11k
      }
112
254k
      seen_ok = true;
113
114
254k
      if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
115
0
        ret = "internal error: frame_rect does not equal dirty_rect";
116
0
        goto exit;
117
0
      }
118
254k
    }
119
1.47k
  }
120
121
2.22k
exit:
122
2.22k
  free(workbuf.ptr);
123
2.22k
  free(pixbuf.ptr);
124
2.22k
  return ret;
125
1.47k
}
jpeg_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
3.36k
                   wuffs_base__image_decoder* dec) {
19
3.36k
  const char* ret = NULL;
20
3.36k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
3.36k
  wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
22
23
  // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
24
  // variable initialization" warnings.
25
3.36k
  {
26
3.36k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
3.36k
    wuffs_base__status status =
28
3.36k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
3.36k
    if (!wuffs_base__status__is_ok(&status)) {
30
936
      ret = wuffs_base__status__message(&status);
31
936
      goto exit;
32
936
    }
33
2.42k
    if (!wuffs_base__image_config__is_valid(&ic)) {
34
0
      ret = "invalid image_config";
35
0
      goto exit;
36
0
    }
37
38
    // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
39
2.42k
    if (hash & 1) {
40
1.22k
      wuffs_base__pixel_config__set(
41
1.22k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.22k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.22k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.22k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.22k
    }
46
2.42k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
2.42k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
2.42k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
20
      ret = "image too large";
53
20
      goto exit;
54
20
    }
55
2.40k
    if (n > 0) {
56
2.40k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
2.40k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
2.40k
    }
62
63
2.40k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
2.40k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
7
      ret = "image too large";
66
7
      goto exit;
67
7
    }
68
2.39k
    if (n > 0) {
69
2.39k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
2.39k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
2.39k
    }
75
76
2.39k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
2.39k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
2.39k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
2.39k
    bool seen_ok = false;
84
2.40k
    while (true) {
85
2.40k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
2.40k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
2.40k
      if (!wuffs_base__status__is_ok(&status)) {
88
11
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
11
        goto exit;
92
11
      }
93
94
2.39k
      status = wuffs_base__image_decoder__decode_frame(
95
2.39k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
2.39k
      wuffs_base__rect_ie_u32 frame_rect =
98
2.39k
          wuffs_base__frame_config__bounds(&fc);
99
2.39k
      wuffs_base__rect_ie_u32 dirty_rect =
100
2.39k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
2.39k
      if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
102
0
        ret = "internal error: frame_rect does not contain dirty_rect";
103
0
        goto exit;
104
0
      }
105
106
2.39k
      if (!wuffs_base__status__is_ok(&status)) {
107
2.38k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
2.38k
          ret = wuffs_base__status__message(&status);
109
2.38k
        }
110
2.38k
        goto exit;
111
2.38k
      }
112
11
      seen_ok = true;
113
114
11
      if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
115
0
        ret = "internal error: frame_rect does not equal dirty_rect";
116
0
        goto exit;
117
0
      }
118
11
    }
119
2.39k
  }
120
121
3.36k
exit:
122
3.36k
  free(workbuf.ptr);
123
3.36k
  free(pixbuf.ptr);
124
3.36k
  return ret;
125
2.39k
}
bmp_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
3.04k
                   wuffs_base__image_decoder* dec) {
19
3.04k
  const char* ret = NULL;
20
3.04k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
3.04k
  wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
22
23
  // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
24
  // variable initialization" warnings.
25
3.04k
  {
26
3.04k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
3.04k
    wuffs_base__status status =
28
3.04k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
3.04k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.37k
      ret = wuffs_base__status__message(&status);
31
1.37k
      goto exit;
32
1.37k
    }
33
1.67k
    if (!wuffs_base__image_config__is_valid(&ic)) {
34
0
      ret = "invalid image_config";
35
0
      goto exit;
36
0
    }
37
38
    // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
39
1.67k
    if (hash & 1) {
40
1.31k
      wuffs_base__pixel_config__set(
41
1.31k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.31k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.31k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.31k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.31k
    }
46
1.67k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
1.67k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
1.67k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
0
      ret = "image too large";
53
0
      goto exit;
54
0
    }
55
1.67k
    if (n > 0) {
56
0
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
0
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
0
    }
62
63
1.67k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
1.67k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
39
      ret = "image too large";
66
39
      goto exit;
67
39
    }
68
1.63k
    if (n > 0) {
69
1.62k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
1.62k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
1.62k
    }
75
76
1.63k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
1.63k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
1.63k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
1.63k
    bool seen_ok = false;
84
1.75k
    while (true) {
85
1.75k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
1.75k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
1.75k
      if (!wuffs_base__status__is_ok(&status)) {
88
117
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
117
        goto exit;
92
117
      }
93
94
1.63k
      status = wuffs_base__image_decoder__decode_frame(
95
1.63k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
1.63k
      wuffs_base__rect_ie_u32 frame_rect =
98
1.63k
          wuffs_base__frame_config__bounds(&fc);
99
1.63k
      wuffs_base__rect_ie_u32 dirty_rect =
100
1.63k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
1.63k
      if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
102
0
        ret = "internal error: frame_rect does not contain dirty_rect";
103
0
        goto exit;
104
0
      }
105
106
1.63k
      if (!wuffs_base__status__is_ok(&status)) {
107
1.52k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
1.52k
          ret = wuffs_base__status__message(&status);
109
1.52k
        }
110
1.52k
        goto exit;
111
1.52k
      }
112
117
      seen_ok = true;
113
114
117
      if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
115
0
        ret = "internal error: frame_rect does not equal dirty_rect";
116
0
        goto exit;
117
0
      }
118
117
    }
119
1.63k
  }
120
121
3.04k
exit:
122
3.04k
  free(workbuf.ptr);
123
3.04k
  free(pixbuf.ptr);
124
3.04k
  return ret;
125
1.63k
}
targa_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
1.21k
                   wuffs_base__image_decoder* dec) {
19
1.21k
  const char* ret = NULL;
20
1.21k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
1.21k
  wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
22
23
  // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
24
  // variable initialization" warnings.
25
1.21k
  {
26
1.21k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
1.21k
    wuffs_base__status status =
28
1.21k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
1.21k
    if (!wuffs_base__status__is_ok(&status)) {
30
260
      ret = wuffs_base__status__message(&status);
31
260
      goto exit;
32
260
    }
33
952
    if (!wuffs_base__image_config__is_valid(&ic)) {
34
0
      ret = "invalid image_config";
35
0
      goto exit;
36
0
    }
37
38
    // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
39
952
    if (hash & 1) {
40
521
      wuffs_base__pixel_config__set(
41
521
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
521
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
521
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
521
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
521
    }
46
952
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
952
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
952
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
0
      ret = "image too large";
53
0
      goto exit;
54
0
    }
55
952
    if (n > 0) {
56
0
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
0
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
0
    }
62
63
952
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
952
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
31
      ret = "image too large";
66
31
      goto exit;
67
31
    }
68
921
    if (n > 0) {
69
892
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
892
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
892
    }
75
76
921
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
921
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
921
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
921
    bool seen_ok = false;
84
974
    while (true) {
85
974
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
974
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
974
      if (!wuffs_base__status__is_ok(&status)) {
88
53
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
53
        goto exit;
92
53
      }
93
94
921
      status = wuffs_base__image_decoder__decode_frame(
95
921
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
921
      wuffs_base__rect_ie_u32 frame_rect =
98
921
          wuffs_base__frame_config__bounds(&fc);
99
921
      wuffs_base__rect_ie_u32 dirty_rect =
100
921
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
921
      if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
102
0
        ret = "internal error: frame_rect does not contain dirty_rect";
103
0
        goto exit;
104
0
      }
105
106
921
      if (!wuffs_base__status__is_ok(&status)) {
107
868
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
868
          ret = wuffs_base__status__message(&status);
109
868
        }
110
868
        goto exit;
111
868
      }
112
53
      seen_ok = true;
113
114
53
      if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
115
0
        ret = "internal error: frame_rect does not equal dirty_rect";
116
0
        goto exit;
117
0
      }
118
53
    }
119
921
  }
120
121
1.21k
exit:
122
1.21k
  free(workbuf.ptr);
123
1.21k
  free(pixbuf.ptr);
124
1.21k
  return ret;
125
921
}