I never "solved" this but I did track down the offending code. I suspect that something in this segment of Quartz code was causing a buffer overrun somewhere deep inside the core - and it only caused a problem on 3G. Some of the setup for this segment is not included but this is definitely where it is happening:
gradient = CGGradientCreateWithColors(space, (CFArrayRef)colors, locations);
CGContextAddPath(context, path);
CGContextSaveGState(context);
CGContextEOClip(context);
transform = CGAffineTransformMakeRotation(1.571f);
tempPath = CGPathCreateMutable();
CGPathAddPath(tempPath, &transform, path);
pathBounds = CGPathGetPathBoundingBox(tempPath);
point = pathBounds.origin;
point2 = CGPointMake(CGRectGetMaxX(pathBounds), CGRectGetMinY(pathBounds));
transform = CGAffineTransformInvert(transform);
point = CGPointApplyAffineTransform(point, transform);
point2 = CGPointApplyAffineTransform(point2, transform);
CGPathRelease(tempPath);
CGContextDrawLinearGradient(context, gradient, point, point2, (kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation));
CGContextRestoreGState(context);
CGGradientRelease(gradient);