Skip to content

Commit f7c5611

Browse files
committed
<third_party/skia> Cherry-pick fix for CVE-2015-1294
Added check for ill-conditioned invert sk_inv_determinant has a guard that the determinant can't get too big so this CL only checks if the determinant gets too small. BUG=492263 Review URL: https://codereview.chromium.org/1188433011 Change-Id: I7304cd7614f17f4267e681868f07c26d3debe655 Reviewed-by: Kai Koehne <[email protected]>
1 parent 6ea558a commit f7c5611

File tree

2 files changed

+65
-36
lines changed

2 files changed

+65
-36
lines changed

chromium/third_party/skia/include/core/SkMatrix.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,12 @@ class SK_API SkMatrix {
650650
SkScalar fMat[9];
651651
mutable SkTRacy<uint32_t> fTypeMask;
652652

653+
/** Are all elements of the matrix finite?
654+
*/
655+
bool isFinite() const;
656+
657+
static void ComputeInv(SkScalar dst[9], const SkScalar src[9], SkScalar invDet, bool isPersp);
658+
653659
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
654660
fMat[kMScaleX] = sx;
655661
fMat[kMSkewX] = 0;

chromium/third_party/skia/src/core/SkMatrix.cpp

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,16 @@ static double sk_inv_determinant(const float mat[9], int isPerspective) {
717717
return 1.0 / det;
718718
}
719719

720+
bool SkMatrix::isFinite() const {
721+
for (int i = 0; i < 9; ++i) {
722+
if (!SkScalarIsFinite(fMat[i])) {
723+
return false;
724+
}
725+
}
726+
727+
return true;
728+
}
729+
720730
void SkMatrix::SetAffineIdentity(SkScalar affine[6]) {
721731
affine[kAScaleX] = 1;
722732
affine[kASkewY] = 0;
@@ -741,6 +751,37 @@ bool SkMatrix::asAffine(SkScalar affine[6]) const {
741751
return true;
742752
}
743753

754+
void SkMatrix::ComputeInv(SkScalar dst[9], const SkScalar src[9], SkScalar invDet, bool isPersp) {
755+
SkASSERT(src != dst);
756+
SkASSERT(src && dst);
757+
758+
if (isPersp) {
759+
dst[kMScaleX] = scross_dscale(src[kMScaleY], src[kMPersp2], src[kMTransY], src[kMPersp1], invDet);
760+
dst[kMSkewX] = scross_dscale(src[kMTransX], src[kMPersp1], src[kMSkewX], src[kMPersp2], invDet);
761+
dst[kMTransX] = scross_dscale(src[kMSkewX], src[kMTransY], src[kMTransX], src[kMScaleY], invDet);
762+
763+
dst[kMSkewY] = scross_dscale(src[kMTransY], src[kMPersp0], src[kMSkewY], src[kMPersp2], invDet);
764+
dst[kMScaleY] = scross_dscale(src[kMScaleX], src[kMPersp2], src[kMTransX], src[kMPersp0], invDet);
765+
dst[kMTransY] = scross_dscale(src[kMTransX], src[kMSkewY], src[kMScaleX], src[kMTransY], invDet);
766+
767+
dst[kMPersp0] = scross_dscale(src[kMSkewY], src[kMPersp1], src[kMScaleY], src[kMPersp0], invDet);
768+
dst[kMPersp1] = scross_dscale(src[kMSkewX], src[kMPersp0], src[kMScaleX], src[kMPersp1], invDet);
769+
dst[kMPersp2] = scross_dscale(src[kMScaleX], src[kMScaleY], src[kMSkewX], src[kMSkewY], invDet);
770+
} else { // not perspective
771+
dst[kMScaleX] = SkDoubleToScalar(src[kMScaleY] * invDet);
772+
dst[kMSkewX] = SkDoubleToScalar(-src[kMSkewX] * invDet);
773+
dst[kMTransX] = dcross_dscale(src[kMSkewX], src[kMTransY], src[kMScaleY], src[kMTransX], invDet);
774+
775+
dst[kMSkewY] = SkDoubleToScalar(-src[kMSkewY] * invDet);
776+
dst[kMScaleY] = SkDoubleToScalar(src[kMScaleX] * invDet);
777+
dst[kMTransY] = dcross_dscale(src[kMSkewY], src[kMTransX], src[kMScaleX], src[kMTransY], invDet);
778+
779+
dst[kMPersp0] = 0;
780+
dst[kMPersp1] = 0;
781+
dst[kMPersp2] = 1;
782+
}
783+
}
784+
744785
bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
745786
SkASSERT(!this->isIdentity());
746787

@@ -784,50 +825,32 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
784825
}
785826

786827
int isPersp = mask & kPerspective_Mask;
787-
double scale = sk_inv_determinant(fMat, isPersp);
828+
double invDet = sk_inv_determinant(fMat, isPersp);
788829

789-
if (scale == 0) { // underflow
830+
if (invDet == 0) { // underflow
790831
return false;
791832
}
792833

793-
if (inv) {
794-
SkMatrix tmp;
795-
if (inv == this) {
796-
inv = &tmp;
797-
}
834+
bool applyingInPlace = (inv == this);
798835

799-
if (isPersp) {
800-
inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2], fMat[kMTransY], fMat[kMPersp1], scale);
801-
inv->fMat[kMSkewX] = scross_dscale(fMat[kMTransX], fMat[kMPersp1], fMat[kMSkewX], fMat[kMPersp2], scale);
802-
inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMTransX], fMat[kMScaleY], scale);
803-
804-
inv->fMat[kMSkewY] = scross_dscale(fMat[kMTransY], fMat[kMPersp0], fMat[kMSkewY], fMat[kMPersp2], scale);
805-
inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2], fMat[kMTransX], fMat[kMPersp0], scale);
806-
inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY], fMat[kMScaleX], fMat[kMTransY], scale);
807-
808-
inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY], fMat[kMPersp1], fMat[kMScaleY], fMat[kMPersp0], scale);
809-
inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX], fMat[kMPersp0], fMat[kMScaleX], fMat[kMPersp1], scale);
810-
inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY], fMat[kMSkewX], fMat[kMSkewY], scale);
811-
} else { // not perspective
812-
inv->fMat[kMScaleX] = SkDoubleToScalar(fMat[kMScaleY] * scale);
813-
inv->fMat[kMSkewX] = SkDoubleToScalar(-fMat[kMSkewX] * scale);
814-
inv->fMat[kMTransX] = dcross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMScaleY], fMat[kMTransX], scale);
815-
816-
inv->fMat[kMSkewY] = SkDoubleToScalar(-fMat[kMSkewY] * scale);
817-
inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale);
818-
inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], fMat[kMScaleX], fMat[kMTransY], scale);
819-
820-
inv->fMat[kMPersp0] = 0;
821-
inv->fMat[kMPersp1] = 0;
822-
inv->fMat[kMPersp2] = 1;
823-
}
836+
SkMatrix* tmp = inv;
837+
838+
SkMatrix storage;
839+
if (applyingInPlace || NULL == tmp) {
840+
tmp = &storage; // we either need to avoid trampling memory or have no memory
841+
}
842+
843+
ComputeInv(tmp->fMat, fMat, invDet, isPersp);
844+
if (!tmp->isFinite()) {
845+
return false;
846+
}
824847

825-
inv->setTypeMask(fTypeMask);
848+
tmp->setTypeMask(fTypeMask);
826849

827-
if (inv == &tmp) {
828-
*(SkMatrix*)this = tmp;
829-
}
850+
if (applyingInPlace) {
851+
*inv = storage; // need to copy answer back
830852
}
853+
831854
return true;
832855
}
833856

0 commit comments

Comments
 (0)