Commit e244e64
gdk-pixbuf: fix memory leaks and API misuse in pixbuf_cons_fuzzer (google#15080)
## Summary
This is **not** a bug in gdk-pixbuf. It is a bug in the fuzz harness
`pixbuf_cons_fuzzer` that causes **memory leaks** (1704 bytes in 8
allocations per iteration) detectable by LeakSanitizer, and an **API
contract violation** (`gdk_pixbuf_scale` with same src and dest).
### False Positive Impact
If left unfixed, any leak report from this fuzzer will be a **false
positive** — the leaks originate in the harness, not in gdk-pixbuf. This
can lead to:
- **Wasted developer time**: Maintainers investigating leak reports that
are not real gdk-pixbuf bugs
- **Noise in OSS-Fuzz dashboards**: Persistent unfixed "bugs" that are
actually harness defects
- **Amplified impact in the AI era**: AI-assisted fuzzing tools
increasingly reference existing OSS-Fuzz harnesses as ground truth. A
buggy harness pattern can be copied and propagated by LLM-based harness
generators, multiplying false positives across downstream projects
### Bugs Fixed
**P1 (Harness Logic)**: Multiple intermediate `GdkPixbuf` objects leaked
— `tmp` is overwritten repeatedly without freeing previous values:
```c
tmp = gdk_pixbuf_rotate_simple(pixbuf, rot_amount * 90); // rotated leaked
tmp = gdk_pixbuf_flip(pixbuf, TRUE); // flipped leaked
tmp = gdk_pixbuf_composite_color_simple(pixbuf, ...); // composite leaked
```
Also, `GBytes` from `g_bytes_new_static()` is never freed.
**P2 (API Protocol)**: `gdk_pixbuf_scale(pixbuf, pixbuf, ...)` uses the
same pixbuf as both source and destination. The [API
documentation](https://docs.gtk.org/gdk-pixbuf/method.Pixbuf.scale.html)
requires they be different.
### LSan Report
```
==14==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 96 byte(s) in 1 object(s) allocated from:
#0 calloc
#1 g_malloc0 (gmem.c:133)
...
#5 gdk_pixbuf_new_from_data (gdk-pixbuf-data.c:79)
#6 LLVMFuzzerTestOneInput (pixbuf_cons_fuzzer.c:65)
SUMMARY: AddressSanitizer: 1704 byte(s) leaked in 8 allocation(s).
```
The leak triggers on the **first seed corpus input** and is 100%
reproducible.
### Fix
1. Free each intermediate `tmp` with `g_object_unref()` before
reassignment
2. Add `g_bytes_unref(bytes)` on all paths
3. Replace `gdk_pixbuf_scale(src==dest)` with
`gdk_pixbuf_scale_simple()`
Co-authored-by: DavidKorczynski <david@adalogics.com>1 parent e946b5e commit e244e64
1 file changed
Lines changed: 18 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
39 | 40 | | |
40 | 41 | | |
41 | | - | |
42 | | - | |
43 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
44 | 45 | | |
45 | | - | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
47 | 49 | | |
48 | 50 | | |
| 51 | + | |
| 52 | + | |
49 | 53 | | |
| 54 | + | |
| 55 | + | |
50 | 56 | | |
51 | | - | |
| 57 | + | |
52 | 58 | | |
53 | 59 | | |
54 | 60 | | |
55 | 61 | | |
56 | 62 | | |
57 | 63 | | |
| 64 | + | |
58 | 65 | | |
59 | 66 | | |
60 | 67 | | |
| |||
66 | 73 | | |
67 | 74 | | |
68 | 75 | | |
69 | | - | |
| 76 | + | |
70 | 77 | | |
71 | 78 | | |
72 | 79 | | |
73 | 80 | | |
74 | | - | |
| 81 | + | |
| 82 | + | |
75 | 83 | | |
76 | 84 | | |
| 85 | + | |
77 | 86 | | |
78 | | - | |
| 87 | + | |
79 | 88 | | |
80 | 89 | | |
0 commit comments