backport_1080481.patch 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Cheng Zhao <[email protected]>
  3. Date: Thu, 4 Oct 2018 14:57:02 -0700
  4. Subject: fix: drop SkTextBlobs with > 2M glyphs
  5. [1080481] [Medium] [CVE-2020-6523]: Security: Skia: Integer Overflow in GrTextBlob::Make
  6. Backport https://skia.googlesource.com/skia.git/+/8d2ebfffaf6ece9a7e9839dca2d7907f241c3460
  7. diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
  8. index 9dd0f16b0b69f3a2f1c592bb0a3755c51fa3a099..3b4a9735d4615591a48b8f7578e3449de2c17c07 100644
  9. --- a/src/core/SkCanvas.cpp
  10. +++ b/src/core/SkCanvas.cpp
  11. @@ -2697,6 +2697,19 @@ void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
  12. TRACE_EVENT0("skia", TRACE_FUNC);
  13. RETURN_ON_NULL(blob);
  14. RETURN_ON_FALSE(blob->bounds().makeOffset(x, y).isFinite());
  15. +
  16. + // Overflow if more than 2^21 glyphs stopping a buffer overflow latter in the stack.
  17. + // See chromium:1080481
  18. + // TODO: can consider unrolling a few at a time if this limit becomes a problem.
  19. + int totalGlyphCount = 0;
  20. + constexpr int kMaxGlyphCount = 1 << 21;
  21. + SkTextBlob::Iter i(*blob);
  22. + SkTextBlob::Iter::Run r;
  23. + while (i.next(&r)) {
  24. + int glyphsLeft = kMaxGlyphCount - totalGlyphCount;
  25. + RETURN_ON_FALSE(r.fGlyphCount <= glyphsLeft);
  26. + totalGlyphCount += r.fGlyphCount;
  27. + }
  28. this->onDrawTextBlob(blob, x, y, paint);
  29. }
  30. diff --git a/tests/TextBlobCacheTest.cpp b/tests/TextBlobCacheTest.cpp
  31. index bcc7288a2afe800706bc924eea5050786347c747..3508221408c801957dfc8d4cb52c6ac3ddd08a77 100644
  32. --- a/tests/TextBlobCacheTest.cpp
  33. +++ b/tests/TextBlobCacheTest.cpp
  34. @@ -229,6 +229,51 @@ static sk_sp<SkTextBlob> make_blob() {
  35. return builder.make();
  36. }
  37. +// Turned off to pass on android and ios devices, which were running out of memory..
  38. +#if 0
  39. +static sk_sp<SkTextBlob> make_large_blob() {
  40. + auto tf = SkTypeface::MakeFromName("Roboto2-Regular", SkFontStyle());
  41. + SkFont font;
  42. + font.setTypeface(tf);
  43. + font.setSubpixel(false);
  44. + font.setEdging(SkFont::Edging::kAlias);
  45. + font.setSize(24);
  46. +
  47. + const int mallocSize = 0x3c3c3bd; // x86 size
  48. + std::unique_ptr<char[]> text{new char[mallocSize + 1]};
  49. + if (text == nullptr) {
  50. + return nullptr;
  51. + }
  52. + for (int i = 0; i < mallocSize; i++) {
  53. + text[i] = 'x';
  54. + }
  55. + text[mallocSize] = 0;
  56. +
  57. + static const int maxGlyphLen = mallocSize;
  58. + std::unique_ptr<SkGlyphID[]> glyphs{new SkGlyphID[maxGlyphLen]};
  59. + int glyphCount =
  60. + font.textToGlyphs(
  61. + text.get(), mallocSize, SkTextEncoding::kUTF8, glyphs.get(), maxGlyphLen);
  62. + SkTextBlobBuilder builder;
  63. + const auto& runBuffer = builder.allocRun(font, glyphCount, 0, 0);
  64. + for (int i = 0; i < glyphCount; i++) {
  65. + runBuffer.glyphs[i] = glyphs[i];
  66. + }
  67. + return builder.make();
  68. +}
  69. +
  70. +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextBlobIntegerOverflowTest, reporter, ctxInfo) {
  71. + auto grContext = ctxInfo.grContext();
  72. + const SkImageInfo info =
  73. + SkImageInfo::Make(kScreenDim, kScreenDim, kN32_SkColorType, kPremul_SkAlphaType);
  74. + auto surface = SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info);
  75. +
  76. + auto blob = make_large_blob();
  77. + int y = 40;
  78. + SkBitmap base = draw_blob(blob.get(), surface.get(), {40, y + 0.0f});
  79. +}
  80. +#endif
  81. +
  82. static const bool kDumpPngs = true;
  83. // dump pngs needs a "good" and a "bad" directory to put the results in. This allows the use of the
  84. // skdiff tool to visualize the differences.