Fix memory leak in Context::pop_group() due to double reference count#1
Open
hana-kami wants to merge 1 commit intoCMakePorts:cmakefrom
Open
Fix memory leak in Context::pop_group() due to double reference count#1hana-kami wants to merge 1 commit intoCMakePorts:cmakefrom
hana-kami wants to merge 1 commit intoCMakePorts:cmakefrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug Description
Context::pop_group()causes a memory leak because it passeshas_reference=falsetoget_pattern_wrapper(), which unconditionallycalls
cairo_pattern_reference()to take an extra reference. However,cairo_pop_group()already returns a pattern with an initial refcount of1 — the caller owns that reference. This results in the refcount being
inflated by 1 and never reaching zero.
Reference Count Trace (before fix)
cairo_pop_group()returns pattern (caller owns it)get_pattern_wrapper(pattern, false)→ callscairo_pattern_reference()cairo_set_source()insideset_source()adds a referenceRefPtr<Pattern>is destroyed →cairo_pattern_destroy()restore()) →cairo_pattern_destroy()This was confirmed with Valgrind:
Root Cause
get_pattern_wrapper()was designed forget_source(), wherecairo_get_source()returns a borrowed reference (the context stillowns it), so the wrapper must call
cairo_pattern_reference()to obtainits own reference (
has_reference=falseis correct there).But
cairo_pop_group()returns a new reference (the caller isresponsible for calling
cairo_pattern_destroy()), so the wrapper mustNOT call
cairo_pattern_reference()again.Fix
Add a
has_referenceparameter (defaulting tofalse) toget_pattern_wrapper()so callers can specify whether they already ownthe reference. Update
pop_group()to passtrue.get_source()continues to use the defaultfalse(borrowed reference → correct).pop_group()now passestrue(owned reference → no extra ref).Testing
Verified with Valgrind that the "definitely lost" leak no longer appears
after applying this fix.