Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f2efb80

Browse files
lhkbobSkia Commit-Bot
authored andcommitted
Clamp really big recording bounds to safe ints
Bug: skia:10997 Change-Id: Ic6da0cbe6dd68009d888bc3174de913852559de7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/338598 Commit-Queue: Michael Ludwig <[email protected]> Reviewed-by: Mike Klein <[email protected]>
1 parent a2c4020 commit f2efb80

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/core/SkRecorder.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,41 @@ void SkDrawableList::append(SkDrawable* drawable) {
4040

4141
///////////////////////////////////////////////////////////////////////////////////////////////
4242

43+
static SkIRect safe_picture_bounds(const SkRect& bounds) {
44+
SkIRect picBounds = bounds.roundOut();
45+
// roundOut() saturates the float edges to +/-SK_MaxS32FitsInFloat (~2billion), but this is
46+
// large enough that width/height calculations will overflow, leading to negative dimensions.
47+
static constexpr int32_t kSafeEdge = SK_MaxS32FitsInFloat / 2 - 1;
48+
static constexpr SkIRect kSafeBounds = {-kSafeEdge, -kSafeEdge, kSafeEdge, kSafeEdge};
49+
static_assert((kSafeBounds.fRight - kSafeBounds.fLeft) >= 0 &&
50+
(kSafeBounds.fBottom - kSafeBounds.fTop) >= 0);
51+
if (!picBounds.intersect(kSafeBounds)) {
52+
picBounds.setEmpty();
53+
}
54+
return picBounds;
55+
}
56+
4357
SkRecorder::SkRecorder(SkRecord* record, int width, int height, SkMiniRecorder* mr)
44-
: SkCanvasVirtualEnforcer<SkNoDrawCanvas>(width, height)
45-
, fApproxBytesUsedBySubPictures(0)
46-
, fRecord(record)
47-
, fMiniRecorder(mr) {}
58+
: SkCanvasVirtualEnforcer<SkNoDrawCanvas>(width, height)
59+
, fApproxBytesUsedBySubPictures(0)
60+
, fRecord(record)
61+
, fMiniRecorder(mr) {
62+
SkASSERT(this->imageInfo().width() >= 0 && this->imageInfo().height() >= 0);
63+
}
4864

4965
SkRecorder::SkRecorder(SkRecord* record, const SkRect& bounds, SkMiniRecorder* mr)
50-
: SkCanvasVirtualEnforcer<SkNoDrawCanvas>(bounds.roundOut())
51-
, fApproxBytesUsedBySubPictures(0)
52-
, fRecord(record)
53-
, fMiniRecorder(mr) {}
66+
: SkCanvasVirtualEnforcer<SkNoDrawCanvas>(safe_picture_bounds(bounds))
67+
, fApproxBytesUsedBySubPictures(0)
68+
, fRecord(record)
69+
, fMiniRecorder(mr) {
70+
SkASSERT(this->imageInfo().width() >= 0 && this->imageInfo().height() >= 0);
71+
}
5472

5573
void SkRecorder::reset(SkRecord* record, const SkRect& bounds, SkMiniRecorder* mr) {
5674
this->forgetRecord();
5775
fRecord = record;
58-
this->resetCanvas(bounds.roundOut());
76+
this->resetCanvas(safe_picture_bounds(bounds));
77+
SkASSERT(this->imageInfo().width() >= 0 && this->imageInfo().height() >= 0);
5978
fMiniRecorder = mr;
6079
}
6180

tests/RecorderTest.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,13 @@ DEF_TEST(Recorder_drawImage_takeReference, reporter) {
108108
}
109109
REPORTER_ASSERT(reporter, image->unique());
110110
}
111+
112+
// skbug.com/10997
113+
DEF_TEST(Recorder_boundsOverflow, reporter) {
114+
SkRect bigBounds = {SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax};
115+
116+
SkRecord record;
117+
SkRecorder recorder(&record, bigBounds);
118+
REPORTER_ASSERT(reporter, recorder.imageInfo().width() > 0 &&
119+
recorder.imageInfo().height() > 0);
120+
}

0 commit comments

Comments
 (0)