Bug 7446

Summary: Infinite recursion in _cairo_surface_composite
Product: cairo Reporter: Dave Vasilevsky <djvasi>
Component: generalAssignee: Carl Worth <cworth>
Status: RESOLVED INVALID QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: high CC: moxfox
Version: 1.2.0   
Hardware: PowerPC   
OS: Mac OS X (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on: 7377    
Bug Blocks:    
Attachments: Test case
Implementation of _cairo_quartz_surface_acquire_source_image
Updated test case

Description Dave Vasilevsky 2006-07-06 12:40:34 UTC
If _cairo_surface_composite cannot use a backend-specific composite function, it falls back to 
_cairo_surface_fallback_composite. Then the destination surface is converted to an image, and 
_cairo_surface_composite is called again, with the expectation that it cannot fail on images.

However, if the original failure was because of the mask or the source surfaces, then 
_cairo_surface_composite may fail again. In this case, _cairo_surface_composite and 
_cairo_surface_fallback_composite recurse infinitely.

The attached test case demonstrates this situation by using a Quartz surface as the source. Since the 
Quartz surface cannot be acquired as an image source, the image backend composite function always 
fails, causing more recursion until the program eventually segfaults when the stack is overrun.

This could be fixed if _cairo_surface_fallback_composite converted the source and mask at the same 
time as the destination. Alternatively, an extra argument could be added to tell 
_cairo_surface_composite not to try falling back any longer.
Comment 1 Owen Taylor 2006-07-06 12:44:42 UTC
I think the problem here is in the Quartz code, not the fallback code.
The Quartz code *cannot* allow a fallback code to be called if it 
can't provide the facilities that the fallback code needs. (Getting
the relevant area of the destination as an image.) 

Since I very much doubt that all of Cairo's compositing modes can
be natively done in Quartz, you really have to fix the lack of the
ability to get the destination surface.
Comment 2 Dave Vasilevsky 2006-07-06 12:49:10 UTC
Owen, it's the source surface that can't be accessed as an image, not the destination surface. But point 
granted, the Quartz backend really should be able to acquire a source surface. I'm working on that right 
now, I have it mostly working--however the solution will have to be OS X 10.4-only, so I'd really like to 
find a way to fix the infinite recursion on 10.3 as well.
Comment 3 Dave Vasilevsky 2006-07-06 12:52:41 UTC
Created attachment 6152 [details]
Test case
Comment 4 Owen Taylor 2006-07-06 12:57:30 UTC
It's certainly valid to have surface types that can't be used as sources ...
that's the case for window surfaces on any platform, really.

I was pretty sure that the code as it existed in the 1.0.x branch handled that
case, but looking at the 1.1.x it's been significantly rewritten, and is
unfamiliar to me, so I'm not sure if it regressed or it never worked.
Comment 5 Dave Vasilevsky 2006-07-06 18:59:38 UTC
Created attachment 6154 [details] [review]
Implementation of _cairo_quartz_surface_acquire_source_image

Here's an implementation of acquire_source_image for the Quartz backend. It
should work for any bitmap image context on Mac OS X 10.4 or later. It should
also compile against earlier versions of OS X. If compiled for 10.4 with
MACOSX_DEPLOYMENT_TARGET=10.3, then it should be weak-linked and can still run
on 10.3.
Comment 6 Dave Vasilevsky 2006-07-06 19:00:15 UTC
Created attachment 6155 [details]
Updated test case
Comment 7 Dave Vasilevsky 2006-07-06 19:03:56 UTC
Note that the bug as originally reported is still present, even if acquire_source_image works on Quartz. 
This just makes it less likely to be encountered.
Comment 8 Carl Worth 2006-07-10 16:17:01 UTC
(In reply to comment #4)
> It's certainly valid to have surface types that can't be used as sources ...
> that's the case for window surfaces on any platform, really.

I don't think we have that codified anywhere.

There's certainly nothing in the documentation of
cairo_pattern_create_for_surface nor any of the cairo_surface_create functions
about possible failures, (nor even an error status that would be appropriate for
this case).

As far as the issue with window surfaces as source, we have said several times
in discussion that that wouldn't be useful, but we've always left it as a "just
don't do that" issue.

As far as I know, we don't currently have a supported surface backend for which
none of its surfaces can be used as part of source patterns. And I'd like to
preserve that characteristic.

-Carl

PS. I haven't looked closely at the conditions for actually triggering this
bug---I just wanted to reply to this one comment I saw.
Comment 9 Owen Taylor 2006-07-11 05:50:51 UTC
We have a long list of issues with windows as source surfaces:

 - There is no guarantee of retention of pixel contents for windows;
   this is OK for output fallbacks, since we only care about getting
   the pixels we are going to draw to (the "interest area"), but drawing
   from an offscreen window to something visible may well produce
   junk.

 - We don't track a useful size for windows. On Windows, we have
   the size only of the interest area (possible empty, have
   we tested the repeat code with a 0x0 surface?) On X, we do have
   the window size, but it allowed to be stale; so transiently, the
   repeat pitch for a fallback operation might be different
   from the pitch of the same operation done via RENDER.

 - I'm pretty sure we don't properly guard all use of windowing system  
   functions that can't handle a window as a source surface; whether
   that is setting the surface as a tile on an X GC, or using AlphaBlend
   on windows.

Some of the above are fixable, some of the above are not fixable. It
seems very much in the spirit of what we do currently, in any case,
for a surface to return UNSUPPORTED from acquire_source_image; the only
reasonable alternative in some cases would be to return a 1x1 transparent
surface, and why should the backend have to do that?
Comment 10 Carl Worth 2006-07-12 07:02:47 UTC
(In reply to comment #9)
> We have a long list of issues with windows as source surfaces:

Yes, I understand that.

> It seems very much in the spirit of what we do currently, in any case,
> for a surface to return UNSUPPORTED from acquire_source_image;

And what do you propose happen after that? There's (obviously) no fallback code
in cairo_surface_acquire_source_image to handle this case. And it's very much
not in the spirit of anything we do currently to advertise any operations as
UNSUPPORTED to the user, (which is why UNSUPPORTED is an internal status value
only, and not public).

That's the point I was trying to make before. I really don't want to start
sprinkling the cairo API with the kind of unreliability that would occur if any
given operation "might not work" in the mind of the user.

-Carl
Comment 11 Owen Taylor 2006-07-12 07:12:20 UTC
Well, I'm not sure how not working but not reporting an error gives more
reliability than not working and reporting an error..

But more specifically: if you think that drawing nothing without reporting 
an error back to theuser is OK, then we might as well do that in the wrapper 
code as compared to making backends implement it individually.
Comment 12 Chris Wilson 2012-04-14 07:49:13 UTC
Obsolete!

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.