diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc index e80c6c3fa919b..c44ecbc59081e 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc @@ -1517,9 +1517,18 @@ void ShapeResult::ComputeGlyphPositions(ShapeResultRun* run, : -HarfBuzzPositionToTextLayoutUnit(pos.y_advance); DCHECK_GE(glyph.cluster, start_cluster); - const uint16_t character_index = glyph.cluster - start_cluster; + uint16_t character_index = glyph.cluster - start_cluster; DCHECK_LE(character_index, HarfBuzzRunGlyphData::kMaxCharacterIndex); DCHECK_LT(character_index, run->num_characters_); + // --- POC INJECTION (simulates crbug.com/1147011 / crbug.com/1286882) --- + // Crash telemetry proves HarfBuzz can emit cluster values that violate the + // DCHECKs above in release builds. We cannot reproduce the exact font, so + // we directly poison the bitfield for a magic-length LTR run to demonstrate + // the unguarded text-emphasis consumer. + if (run->num_characters_ == 13 && run->IsLtr() && i == num_glyphs - 1) { + character_index = 30000; // fits in 15-bit bitfield + } + // ---------------------------------------------------------------------- run->glyph_data_[i] = { glyph.codepoint, character_index, SafeToBreakBefore(UNSAFE_TODO(glyph_infos + start_glyph), i, num_glyphs, diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc index 22df60767ddce..aea3bfeab9bcb 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc @@ -371,7 +371,14 @@ class ClusterCallbackContext { gfx::PointF glyph_center = parsed_context->glyph_center; if (text.Is8Bit()) { - if (Character::CanReceiveTextEmphasis(text[character_index])) { + // --- POC: release-build-equivalent access --- + // In release (non-ASan) builds, StringView::operator[] is exactly: + // SECURITY_DCHECK(i < length()); // -> ((void)0) + // return static_cast(bytes_)[i]; + // We inline that here so ASan can observe the OOB read instead of the + // ASan-only SECURITY_DCHECK masking it. + const LChar* raw = static_cast(text.Bytes()); + if (Character::CanReceiveTextEmphasis(UNSAFE_BUFFERS(raw[character_index]))) { bloberizer->AddEmphasisMark(emphasis_data, canvas_rotation, glyph_center, advance_so_far + cluster_advance / 2, parsed_context->letter_spacing);