[comp.sys.mac.programmer] Quickdraw bug

kaufman@polya.Stanford.EDU (Marc T. Kaufman) (07/06/88)

FYI: I have uncovered a bug in Quickdraw that can trash memory.
Environment:  8-bit pixel, rowbytes > 4000 (e.g. 6000).  Draw a line from
above the pixmap to below the pixmap, going through the pixmap.  Quickdraw
will set pixels in the row [portRect.top -1].  If the portPixMap is not enough
bigger than the portRect to contain the extra row at the top, these pixels
are set on whatever happens to be in memory... (such as your code).

Just thought you all would like to know.

Marc Kaufman (kaufman@polya.stanford.edu)

olson@endor.harvard.edu (Eric K. Olson) (07/07/88)

In a recent article Marc T. Kaufman writes:
>FYI: I have uncovered a bug in Quickdraw that can trash memory.
>Environment:  8-bit pixel, rowbytes > 4000 (e.g. 6000).  Draw a line from

I believe that rowBytes must be less than 4096, and that the high-order
bits are used as flags.

-Eric


          Lexington Software Design:  Tomorrow's Software Yesterday

Eric K. Olson     olson@endor.harvard.edu     harvard!endor!olson     D0760
   (Name)                (ArpaNet)                 (UseNet)        (AppleLink)

kaufman@polya.Stanford.EDU (Marc T. Kaufman) (07/07/88)

In article <4899@husc6.harvard.edu> olson@endor.UUCP (Eric K. Olson) writes:
>In a recent article Marc T. Kaufman writes:
->FYI: I have uncovered a bug in Quickdraw that can trash memory.
->Environment:  8-bit pixel, rowbytes > 4000 (e.g. 6000).  Draw a line from

>I believe that rowBytes must be less than 4096, and that the high-order
>bits are used as flags.

rowBytes must be <= 8190.  The high order 3 bits are flags.  See my earlier
posting about rowbytes > 8190.  'lsr'@apple says that a new version of the
PixMap will have a longint for rowBytes (but where will they put it?).  This
is needed because in 32-bit color mode 8190 bytes is only 2047 pixels per row.

Marc Kaufman (kaufman@polya.stanford.edu)

lsr@Apple.COM (Larry Rosenstein) (07/08/88)

In article <3178@polya.Stanford.EDU> kaufman@polya.Stanford.EDU (Marc T. Kaufman) writes:
>posting about rowbytes > 8190.  'lsr'@apple says that a new version of the
>PixMap will have a longint for rowBytes (but where will they put it?).  This
>is needed because in 32-bit color mode 8190 bytes is only 2047 pixels per row.

That is NOT what I said.  

I said that the Color Quickdraw data structures (in particular the PixMap
and CGrafPort) have version fields.  It seems to me that Apple could use
this field to implement a new version of the Pixmap that allows more pixels
per row, without breaking applications.  (Inside Mac defines the current
version number as 0.)  These structures also contain a reserved field that
might be used to contain any extra data needed by future versions.

Whether or not there WILL BE a new version of the data structures is up to
the graphics people implementing the stuff.  I don't know what their plans
are.

		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 27-AJ  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr

russotto@eng.umd.edu (Matthew T. Russotto) (07/04/90)

OK, here goes.  I tried to post this once before, but it didn't seem to make
it.  Basically the problem occurs with long, thin, single bit bitmaps.
      	tmpport = NewPtr((long)sizeof(GrafPort));
      	OpenPort(tmpport);
      	bm.baseAddr = NewPtr(0xC000L/8L);
      	bm.rowBytes = (short)(0xC000L/8L);
      	bm.bounds.left = -24576;
      	bm.bounds.top = 0;
    	bm.bounds.right = 0x6000;
    	bm.bounds.bottom = 1;
    	SetPortBits(&bm);
	BlockMove(&bm.bounds, &tmpport->portRect, (long)sizeof(Rect));
	RectRgn(tmpport->visRgn, &bm.bounds);
	ClipRect(&bm.bounds);
    	EraseRect(&bm.bounds);
		^^^^^^^^ hangs here, at the eraserect.
Also, any drawing past pen location 0x2000 (the 0x8000th bit in the image,
not coincidentally, I am sure) has no effect.
Sure, this is a horrible abuse of Quickdraw, but QD should perform up to spec.
--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?
		Hey!  Bush has NO LIPS!

d_volaric@vaxa.cc.uwa.oz.au (07/13/90)

In article <1990Jul4.023022.10833@eng.umd.edu>, russotto@eng.umd.edu (Matthew T. Russotto) writes:
> OK, here goes.  I tried to post this once before, but it didn't seem to make
> it.  Basically the problem occurs with long, thin, single bit bitmaps.
>       	tmpport = NewPtr((long)sizeof(GrafPort));
>       	OpenPort(tmpport);
>       	bm.baseAddr = NewPtr(0xC000L/8L);
>       	bm.rowBytes = (short)(0xC000L/8L);
>       	bm.bounds.left = -24576;
>       	bm.bounds.top = 0;
>     	bm.bounds.right = 0x6000;
>     	bm.bounds.bottom = 1;
>     	SetPortBits(&bm);
> 	BlockMove(&bm.bounds, &tmpport->portRect, (long)sizeof(Rect));
> 	RectRgn(tmpport->visRgn, &bm.bounds);
> 	ClipRect(&bm.bounds);
>     	EraseRect(&bm.bounds);
> 		^^^^^^^^ hangs here, at the eraserect.
> Sure, this is a horrible abuse of Quickdraw, but QD should perform up to spec.

What do you expect? Deep inside QuickDraw, it calculates the width of the rect,
and uses it for its own private magic. This happens long after the code has 
given up on range checking, and the result is put into an integer. Lets 
calculate the width of your rect, and see what we get... $6000-(-$6000)=$C000=
-$4000!!!!! Whats this? drawing a negative width rect into a negative width 
grafport? I'm suprised you got away with a mere crash!

John
-------------------------------------------------------------------------------
                          D V O R A K    C O M P U T E R
Phone : +61 9 330 2876    The Bunker, Rear 57 Holman Street, 
                          Alfred Cove,  Western Australia, 6154.
                          P.O. Box 315, Melville, WA, 6156.
-------------------------------------------------------------------------------