Coverage Report

Created: 2025-12-31 06:41

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
16.4k
                   wuffs_base__image_decoder* dec) {
19
16.4k
  const char* ret = NULL;
20
16.4k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
16.4k
  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
16.4k
  {
26
16.4k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
16.4k
    wuffs_base__status status =
28
16.4k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
16.4k
    if (!wuffs_base__status__is_ok(&status)) {
30
5.29k
      ret = wuffs_base__status__message(&status);
31
5.29k
      goto exit;
32
5.29k
    }
33
11.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
11.1k
    if (hash & 1) {
40
6.13k
      wuffs_base__pixel_config__set(
41
6.13k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
6.13k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
6.13k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
6.13k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
6.13k
    }
46
11.1k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
11.1k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
11.1k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
39
      ret = "image too large";
53
39
      goto exit;
54
39
    }
55
11.1k
    if (n > 0) {
56
6.92k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
6.92k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
6.92k
    }
62
63
11.1k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
11.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.9k
    if (n > 0) {
69
10.7k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
10.7k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
10.7k
    }
75
76
10.9k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
10.9k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
10.9k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
10.9k
    bool seen_ok = false;
84
262k
    while (true) {
85
262k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
262k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
262k
      if (!wuffs_base__status__is_ok(&status)) {
88
957
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
718
          ret = wuffs_base__status__message(&status);
90
718
        }
91
957
        goto exit;
92
957
      }
93
94
261k
      status = wuffs_base__image_decoder__decode_frame(
95
261k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
261k
      wuffs_base__rect_ie_u32 frame_rect =
98
261k
          wuffs_base__frame_config__bounds(&fc);
99
261k
      wuffs_base__rect_ie_u32 dirty_rect =
100
261k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
261k
      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
261k
      if (!wuffs_base__status__is_ok(&status)) {
107
10.0k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
10.0k
          ret = wuffs_base__status__message(&status);
109
10.0k
        }
110
10.0k
        goto exit;
111
10.0k
      }
112
251k
      seen_ok = true;
113
114
251k
      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
251k
    }
119
10.9k
  }
120
121
16.4k
exit:
122
16.4k
  free(workbuf.ptr);
123
16.4k
  free(pixbuf.ptr);
124
16.4k
  return ret;
125
10.9k
}
png_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
6.06k
                   wuffs_base__image_decoder* dec) {
19
6.06k
  const char* ret = NULL;
20
6.06k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
6.06k
  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
6.06k
  {
26
6.06k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
6.06k
    wuffs_base__status status =
28
6.06k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
6.06k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.86k
      ret = wuffs_base__status__message(&status);
31
1.86k
      goto exit;
32
1.86k
    }
33
4.19k
    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
4.19k
    if (hash & 1) {
40
2.11k
      wuffs_base__pixel_config__set(
41
2.11k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
2.11k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
2.11k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
2.11k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
2.11k
    }
46
4.19k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
4.19k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
4.19k
    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
4.19k
    if (n > 0) {
56
4.19k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
4.19k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
4.19k
    }
62
63
4.19k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
4.19k
    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
4.19k
    if (n > 0) {
69
4.19k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
4.19k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
4.19k
    }
75
76
4.19k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
4.19k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
4.19k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
4.19k
    bool seen_ok = false;
84
6.57k
    while (true) {
85
6.57k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
6.57k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
6.57k
      if (!wuffs_base__status__is_ok(&status)) {
88
416
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
415
          ret = wuffs_base__status__message(&status);
90
415
        }
91
416
        goto exit;
92
416
      }
93
94
6.15k
      status = wuffs_base__image_decoder__decode_frame(
95
6.15k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
6.15k
      wuffs_base__rect_ie_u32 frame_rect =
98
6.15k
          wuffs_base__frame_config__bounds(&fc);
99
6.15k
      wuffs_base__rect_ie_u32 dirty_rect =
100
6.15k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
6.15k
      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
6.15k
      if (!wuffs_base__status__is_ok(&status)) {
107
3.77k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
3.77k
          ret = wuffs_base__status__message(&status);
109
3.77k
        }
110
3.77k
        goto exit;
111
3.77k
      }
112
2.38k
      seen_ok = true;
113
114
2.38k
      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
2.38k
    }
119
4.19k
  }
120
121
6.06k
exit:
122
6.06k
  free(workbuf.ptr);
123
6.06k
  free(pixbuf.ptr);
124
6.06k
  return ret;
125
4.19k
}
gif_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
2.26k
                   wuffs_base__image_decoder* dec) {
19
2.26k
  const char* ret = NULL;
20
2.26k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
2.26k
  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.26k
  {
26
2.26k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
2.26k
    wuffs_base__status status =
28
2.26k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
2.26k
    if (!wuffs_base__status__is_ok(&status)) {
30
701
      ret = wuffs_base__status__message(&status);
31
701
      goto exit;
32
701
    }
33
1.56k
    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.56k
    if (hash & 1) {
40
777
      wuffs_base__pixel_config__set(
41
777
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
777
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
777
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
777
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
777
    }
46
1.56k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
1.56k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
1.56k
    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.56k
    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.56k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
1.56k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
66
      ret = "image too large";
66
66
      goto exit;
67
66
    }
68
1.50k
    if (n > 0) {
69
1.32k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
1.32k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
1.32k
    }
75
76
1.50k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
1.50k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
1.50k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
1.50k
    bool seen_ok = false;
84
250k
    while (true) {
85
250k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
250k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
250k
      if (!wuffs_base__status__is_ok(&status)) {
88
365
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
303
          ret = wuffs_base__status__message(&status);
90
303
        }
91
365
        goto exit;
92
365
      }
93
94
250k
      status = wuffs_base__image_decoder__decode_frame(
95
250k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
250k
      wuffs_base__rect_ie_u32 frame_rect =
98
250k
          wuffs_base__frame_config__bounds(&fc);
99
250k
      wuffs_base__rect_ie_u32 dirty_rect =
100
250k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
250k
      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
250k
      if (!wuffs_base__status__is_ok(&status)) {
107
1.13k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
1.13k
          ret = wuffs_base__status__message(&status);
109
1.13k
        }
110
1.13k
        goto exit;
111
1.13k
      }
112
249k
      seen_ok = true;
113
114
249k
      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
249k
    }
119
1.50k
  }
120
121
2.26k
exit:
122
2.26k
  free(workbuf.ptr);
123
2.26k
  free(pixbuf.ptr);
124
2.26k
  return ret;
125
1.50k
}
jpeg_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
3.83k
                   wuffs_base__image_decoder* dec) {
19
3.83k
  const char* ret = NULL;
20
3.83k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
3.83k
  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.83k
  {
26
3.83k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
3.83k
    wuffs_base__status status =
28
3.83k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
3.83k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.06k
      ret = wuffs_base__status__message(&status);
31
1.06k
      goto exit;
32
1.06k
    }
33
2.76k
    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.76k
    if (hash & 1) {
40
1.41k
      wuffs_base__pixel_config__set(
41
1.41k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.41k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.41k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.41k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.41k
    }
46
2.76k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
2.76k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
2.76k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
31
      ret = "image too large";
53
31
      goto exit;
54
31
    }
55
2.73k
    if (n > 0) {
56
2.73k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
2.73k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
2.73k
    }
62
63
2.73k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
2.73k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
8
      ret = "image too large";
66
8
      goto exit;
67
8
    }
68
2.72k
    if (n > 0) {
69
2.72k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
2.72k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
2.72k
    }
75
76
2.72k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
2.72k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
2.72k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
2.72k
    bool seen_ok = false;
84
2.73k
    while (true) {
85
2.73k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
2.73k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
2.73k
      if (!wuffs_base__status__is_ok(&status)) {
88
4
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
4
        goto exit;
92
4
      }
93
94
2.72k
      status = wuffs_base__image_decoder__decode_frame(
95
2.72k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
2.72k
      wuffs_base__rect_ie_u32 frame_rect =
98
2.72k
          wuffs_base__frame_config__bounds(&fc);
99
2.72k
      wuffs_base__rect_ie_u32 dirty_rect =
100
2.72k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
2.72k
      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.72k
      if (!wuffs_base__status__is_ok(&status)) {
107
2.72k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
2.72k
          ret = wuffs_base__status__message(&status);
109
2.72k
        }
110
2.72k
        goto exit;
111
2.72k
      }
112
4
      seen_ok = true;
113
114
4
      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
4
    }
119
2.72k
  }
120
121
3.83k
exit:
122
3.83k
  free(workbuf.ptr);
123
3.83k
  free(pixbuf.ptr);
124
3.83k
  return ret;
125
2.72k
}
bmp_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
3.06k
                   wuffs_base__image_decoder* dec) {
19
3.06k
  const char* ret = NULL;
20
3.06k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
3.06k
  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.06k
  {
26
3.06k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
3.06k
    wuffs_base__status status =
28
3.06k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
3.06k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.39k
      ret = wuffs_base__status__message(&status);
31
1.39k
      goto exit;
32
1.39k
    }
33
1.66k
    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.66k
    if (hash & 1) {
40
1.29k
      wuffs_base__pixel_config__set(
41
1.29k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.29k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.29k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.29k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.29k
    }
46
1.66k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
1.66k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
1.66k
    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.66k
    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.66k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
1.66k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
36
      ret = "image too large";
66
36
      goto exit;
67
36
    }
68
1.63k
    if (n > 0) {
69
1.61k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
1.61k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
1.61k
    }
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.74k
    while (true) {
85
1.74k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
1.74k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
1.74k
      if (!wuffs_base__status__is_ok(&status)) {
88
118
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
118
        goto exit;
92
118
      }
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.51k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
1.51k
          ret = wuffs_base__status__message(&status);
109
1.51k
        }
110
1.51k
        goto exit;
111
1.51k
      }
112
118
      seen_ok = true;
113
114
118
      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
118
    }
119
1.63k
  }
120
121
3.06k
exit:
122
3.06k
  free(workbuf.ptr);
123
3.06k
  free(pixbuf.ptr);
124
3.06k
  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
267
      ret = wuffs_base__status__message(&status);
31
267
      goto exit;
32
267
    }
33
946
    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
946
    if (hash & 1) {
40
531
      wuffs_base__pixel_config__set(
41
531
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
531
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
531
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
531
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
531
    }
46
946
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
946
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
946
    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
946
    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
946
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
946
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
27
      ret = "image too large";
66
27
      goto exit;
67
27
    }
68
919
    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
919
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
919
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
919
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
919
    bool seen_ok = false;
84
973
    while (true) {
85
973
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
973
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
973
      if (!wuffs_base__status__is_ok(&status)) {
88
54
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
54
        goto exit;
92
54
      }
93
94
919
      status = wuffs_base__image_decoder__decode_frame(
95
919
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
919
      wuffs_base__rect_ie_u32 frame_rect =
98
919
          wuffs_base__frame_config__bounds(&fc);
99
919
      wuffs_base__rect_ie_u32 dirty_rect =
100
919
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
919
      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
919
      if (!wuffs_base__status__is_ok(&status)) {
107
865
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
865
          ret = wuffs_base__status__message(&status);
109
865
        }
110
865
        goto exit;
111
865
      }
112
54
      seen_ok = true;
113
114
54
      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
54
    }
119
919
  }
120
121
1.21k
exit:
122
1.21k
  free(workbuf.ptr);
123
1.21k
  free(pixbuf.ptr);
124
1.21k
  return ret;
125
919
}