Coverage Report

Created: 2025-11-16 06:59

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
15.4k
                   wuffs_base__image_decoder* dec) {
19
15.4k
  const char* ret = NULL;
20
15.4k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
15.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
15.4k
  {
26
15.4k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
15.4k
    wuffs_base__status status =
28
15.4k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
15.4k
    if (!wuffs_base__status__is_ok(&status)) {
30
5.01k
      ret = wuffs_base__status__message(&status);
31
5.01k
      goto exit;
32
5.01k
    }
33
10.4k
    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.4k
    if (hash & 1) {
40
5.74k
      wuffs_base__pixel_config__set(
41
5.74k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
5.74k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
5.74k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
5.74k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
5.74k
    }
46
10.4k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
10.4k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
10.4k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
24
      ret = "image too large";
53
24
      goto exit;
54
24
    }
55
10.4k
    if (n > 0) {
56
6.41k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
6.41k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
6.41k
    }
62
63
10.4k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
10.4k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
128
      ret = "image too large";
66
128
      goto exit;
67
128
    }
68
10.3k
    if (n > 0) {
69
10.1k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
10.1k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
10.1k
    }
75
76
10.3k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
10.3k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
10.3k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
10.3k
    bool seen_ok = false;
84
264k
    while (true) {
85
264k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
264k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
264k
      if (!wuffs_base__status__is_ok(&status)) {
88
964
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
701
          ret = wuffs_base__status__message(&status);
90
701
        }
91
964
        goto exit;
92
964
      }
93
94
263k
      status = wuffs_base__image_decoder__decode_frame(
95
263k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
263k
      wuffs_base__rect_ie_u32 frame_rect =
98
263k
          wuffs_base__frame_config__bounds(&fc);
99
263k
      wuffs_base__rect_ie_u32 dirty_rect =
100
263k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
263k
      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
263k
      if (!wuffs_base__status__is_ok(&status)) {
107
9.33k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
9.33k
          ret = wuffs_base__status__message(&status);
109
9.33k
        }
110
9.33k
        goto exit;
111
9.33k
      }
112
253k
      seen_ok = true;
113
114
253k
      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
253k
    }
119
10.3k
  }
120
121
15.4k
exit:
122
15.4k
  free(workbuf.ptr);
123
15.4k
  free(pixbuf.ptr);
124
15.4k
  return ret;
125
10.3k
}
png_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
5.62k
                   wuffs_base__image_decoder* dec) {
19
5.62k
  const char* ret = NULL;
20
5.62k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
5.62k
  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.62k
  {
26
5.62k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
5.62k
    wuffs_base__status status =
28
5.62k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
5.62k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.70k
      ret = wuffs_base__status__message(&status);
31
1.70k
      goto exit;
32
1.70k
    }
33
3.92k
    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.92k
    if (hash & 1) {
40
1.98k
      wuffs_base__pixel_config__set(
41
1.98k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.98k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.98k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.98k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.98k
    }
46
3.92k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
3.92k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
3.92k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
7
      ret = "image too large";
53
7
      goto exit;
54
7
    }
55
3.91k
    if (n > 0) {
56
3.91k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
3.91k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
3.91k
    }
62
63
3.91k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
3.91k
    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.91k
    if (n > 0) {
69
3.91k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
3.91k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
3.91k
    }
75
76
3.91k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
3.91k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
3.91k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
3.91k
    bool seen_ok = false;
84
6.38k
    while (true) {
85
6.38k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
6.38k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
6.38k
      if (!wuffs_base__status__is_ok(&status)) {
88
416
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
413
          ret = wuffs_base__status__message(&status);
90
413
        }
91
416
        goto exit;
92
416
      }
93
94
5.96k
      status = wuffs_base__image_decoder__decode_frame(
95
5.96k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
5.96k
      wuffs_base__rect_ie_u32 frame_rect =
98
5.96k
          wuffs_base__frame_config__bounds(&fc);
99
5.96k
      wuffs_base__rect_ie_u32 dirty_rect =
100
5.96k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
5.96k
      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.96k
      if (!wuffs_base__status__is_ok(&status)) {
107
3.50k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
3.50k
          ret = wuffs_base__status__message(&status);
109
3.50k
        }
110
3.50k
        goto exit;
111
3.50k
      }
112
2.46k
      seen_ok = true;
113
114
2.46k
      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.46k
    }
119
3.91k
  }
120
121
5.62k
exit:
122
5.62k
  free(workbuf.ptr);
123
5.62k
  free(pixbuf.ptr);
124
5.62k
  return ret;
125
3.91k
}
gif_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
2.11k
                   wuffs_base__image_decoder* dec) {
19
2.11k
  const char* ret = NULL;
20
2.11k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
2.11k
  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.11k
  {
26
2.11k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
2.11k
    wuffs_base__status status =
28
2.11k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
2.11k
    if (!wuffs_base__status__is_ok(&status)) {
30
661
      ret = wuffs_base__status__message(&status);
31
661
      goto exit;
32
661
    }
33
1.45k
    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.45k
    if (hash & 1) {
40
699
      wuffs_base__pixel_config__set(
41
699
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
699
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
699
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
699
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
699
    }
46
1.45k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
1.45k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
1.45k
    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.45k
    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.45k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
1.45k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
59
      ret = "image too large";
66
59
      goto exit;
67
59
    }
68
1.39k
    if (n > 0) {
69
1.25k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
1.25k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
1.25k
    }
75
76
1.39k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
1.39k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
1.39k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
1.39k
    bool seen_ok = false;
84
252k
    while (true) {
85
252k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
252k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
252k
      if (!wuffs_base__status__is_ok(&status)) {
88
351
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
288
          ret = wuffs_base__status__message(&status);
90
288
        }
91
351
        goto exit;
92
351
      }
93
94
252k
      status = wuffs_base__image_decoder__decode_frame(
95
252k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
252k
      wuffs_base__rect_ie_u32 frame_rect =
98
252k
          wuffs_base__frame_config__bounds(&fc);
99
252k
      wuffs_base__rect_ie_u32 dirty_rect =
100
252k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
252k
      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
252k
      if (!wuffs_base__status__is_ok(&status)) {
107
1.04k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
1.04k
          ret = wuffs_base__status__message(&status);
109
1.04k
        }
110
1.04k
        goto exit;
111
1.04k
      }
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
1.39k
  }
120
121
2.11k
exit:
122
2.11k
  free(workbuf.ptr);
123
2.11k
  free(pixbuf.ptr);
124
2.11k
  return ret;
125
1.39k
}
jpeg_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
3.52k
                   wuffs_base__image_decoder* dec) {
19
3.52k
  const char* ret = NULL;
20
3.52k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
3.52k
  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.52k
  {
26
3.52k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
3.52k
    wuffs_base__status status =
28
3.52k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
3.52k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.01k
      ret = wuffs_base__status__message(&status);
31
1.01k
      goto exit;
32
1.01k
    }
33
2.51k
    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.51k
    if (hash & 1) {
40
1.28k
      wuffs_base__pixel_config__set(
41
1.28k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.28k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.28k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.28k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.28k
    }
46
2.51k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
2.51k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
2.51k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
52
17
      ret = "image too large";
53
17
      goto exit;
54
17
    }
55
2.49k
    if (n > 0) {
56
2.49k
      workbuf = wuffs_base__malloc_slice_u8(malloc, n);
57
2.49k
      if (!workbuf.ptr) {
58
0
        ret = "out of memory";
59
0
        goto exit;
60
0
      }
61
2.49k
    }
62
63
2.49k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
2.49k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
5
      ret = "image too large";
66
5
      goto exit;
67
5
    }
68
2.49k
    if (n > 0) {
69
2.49k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
2.49k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
2.49k
    }
75
76
2.49k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
2.49k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
2.49k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
2.49k
    bool seen_ok = false;
84
2.50k
    while (true) {
85
2.50k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
2.50k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
2.50k
      if (!wuffs_base__status__is_ok(&status)) {
88
8
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
8
        goto exit;
92
8
      }
93
94
2.49k
      status = wuffs_base__image_decoder__decode_frame(
95
2.49k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
2.49k
      wuffs_base__rect_ie_u32 frame_rect =
98
2.49k
          wuffs_base__frame_config__bounds(&fc);
99
2.49k
      wuffs_base__rect_ie_u32 dirty_rect =
100
2.49k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
2.49k
      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.49k
      if (!wuffs_base__status__is_ok(&status)) {
107
2.48k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
2.48k
          ret = wuffs_base__status__message(&status);
109
2.48k
        }
110
2.48k
        goto exit;
111
2.48k
      }
112
8
      seen_ok = true;
113
114
8
      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
8
    }
119
2.49k
  }
120
121
3.52k
exit:
122
3.52k
  free(workbuf.ptr);
123
3.52k
  free(pixbuf.ptr);
124
3.52k
  return ret;
125
2.49k
}
bmp_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
3.01k
                   wuffs_base__image_decoder* dec) {
19
3.01k
  const char* ret = NULL;
20
3.01k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
3.01k
  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.01k
  {
26
3.01k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
3.01k
    wuffs_base__status status =
28
3.01k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
3.01k
    if (!wuffs_base__status__is_ok(&status)) {
30
1.38k
      ret = wuffs_base__status__message(&status);
31
1.38k
      goto exit;
32
1.38k
    }
33
1.62k
    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.62k
    if (hash & 1) {
40
1.25k
      wuffs_base__pixel_config__set(
41
1.25k
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
1.25k
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
1.25k
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
1.25k
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
1.25k
    }
46
1.62k
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
1.62k
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
1.62k
    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.62k
    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.62k
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
1.62k
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
38
      ret = "image too large";
66
38
      goto exit;
67
38
    }
68
1.58k
    if (n > 0) {
69
1.57k
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
1.57k
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
1.57k
    }
75
76
1.58k
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
1.58k
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
1.58k
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
1.58k
    bool seen_ok = false;
84
1.72k
    while (true) {
85
1.72k
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
1.72k
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
1.72k
      if (!wuffs_base__status__is_ok(&status)) {
88
133
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
133
        goto exit;
92
133
      }
93
94
1.58k
      status = wuffs_base__image_decoder__decode_frame(
95
1.58k
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
1.58k
      wuffs_base__rect_ie_u32 frame_rect =
98
1.58k
          wuffs_base__frame_config__bounds(&fc);
99
1.58k
      wuffs_base__rect_ie_u32 dirty_rect =
100
1.58k
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
1.58k
      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.58k
      if (!wuffs_base__status__is_ok(&status)) {
107
1.45k
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
1.45k
          ret = wuffs_base__status__message(&status);
109
1.45k
        }
110
1.45k
        goto exit;
111
1.45k
      }
112
133
      seen_ok = true;
113
114
133
      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
133
    }
119
1.58k
  }
120
121
3.01k
exit:
122
3.01k
  free(workbuf.ptr);
123
3.01k
  free(pixbuf.ptr);
124
3.01k
  return ret;
125
1.58k
}
targa_fuzzer.c:fuzz_image_decoder
Line
Count
Source
18
1.18k
                   wuffs_base__image_decoder* dec) {
19
1.18k
  const char* ret = NULL;
20
1.18k
  wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
21
1.18k
  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.18k
  {
26
1.18k
    wuffs_base__image_config ic = ((wuffs_base__image_config){});
27
1.18k
    wuffs_base__status status =
28
1.18k
        wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
29
1.18k
    if (!wuffs_base__status__is_ok(&status)) {
30
254
      ret = wuffs_base__status__message(&status);
31
254
      goto exit;
32
254
    }
33
933
    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
933
    if (hash & 1) {
40
518
      wuffs_base__pixel_config__set(
41
518
          &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
42
518
          WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
43
518
          wuffs_base__pixel_config__width(&ic.pixcfg),
44
518
          wuffs_base__pixel_config__height(&ic.pixcfg));
45
518
    }
46
933
    hash >>= 1;
47
48
    // Wuffs allows either statically or dynamically allocated work buffers.
49
    // This program exercises dynamic allocation.
50
933
    uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
51
933
    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
933
    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
933
    n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
64
933
    if (n > 64 * 1024 * 1024) {  // Don't allocate more than 64 MiB.
65
25
      ret = "image too large";
66
25
      goto exit;
67
25
    }
68
908
    if (n > 0) {
69
879
      pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
70
879
      if (!pixbuf.ptr) {
71
0
        ret = "out of memory";
72
0
        goto exit;
73
0
      }
74
879
    }
75
76
908
    wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
77
908
    status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
78
908
    if (!wuffs_base__status__is_ok(&status)) {
79
0
      ret = wuffs_base__status__message(&status);
80
0
      goto exit;
81
0
    }
82
83
908
    bool seen_ok = false;
84
964
    while (true) {
85
964
      wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
86
964
      status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
87
964
      if (!wuffs_base__status__is_ok(&status)) {
88
56
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
89
0
          ret = wuffs_base__status__message(&status);
90
0
        }
91
56
        goto exit;
92
56
      }
93
94
908
      status = wuffs_base__image_decoder__decode_frame(
95
908
          dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
96
97
908
      wuffs_base__rect_ie_u32 frame_rect =
98
908
          wuffs_base__frame_config__bounds(&fc);
99
908
      wuffs_base__rect_ie_u32 dirty_rect =
100
908
          wuffs_base__image_decoder__frame_dirty_rect(dec);
101
908
      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
908
      if (!wuffs_base__status__is_ok(&status)) {
107
852
        if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
108
852
          ret = wuffs_base__status__message(&status);
109
852
        }
110
852
        goto exit;
111
852
      }
112
56
      seen_ok = true;
113
114
56
      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
56
    }
119
908
  }
120
121
1.18k
exit:
122
1.18k
  free(workbuf.ptr);
123
1.18k
  free(pixbuf.ptr);
124
1.18k
  return ret;
125
908
}