Почему этот тег iframe приводит к сбою Safari в 64-разрядной версии Windows?
Если вы не слышали, этот кусок кода вызовет сбой BSoD на 64-битной Windows 7 при запуске в Safari
<iframe height='18082563'></iframe>
Поэтому, естественно, возникает вопрос, как именно это происходит, и почему 18082563, а не сказать "1808256 4"?
2 ответа
Это объяснение этому.
Ошибка возникает из-за запроса NineGrid, поступающего через GdiDrawStream, отправляемого от имени библиотеки тем UX, которая обрабатывает темы Windows, начиная с XP и позже.
Браузеры Webkit (наряду с IE8 - но не IE9, казалось бы) пытаются отображать HTML-элементы на странице, используя собственный скин ОС. В этом случае в функции drawControl (см. http://www.opensource.apple.com/source/WebCore/WebCore-658.28/rendering/RenderThemeWin.cpp) вызывается DrawThemeBackground, которое обрабатывает скины элементов управления ОС.
Отправляется 96-байтовый буфер (0x60) (параметры 2 и 3 GdiDrawStream - это размер и адрес буфера, параметр 1 - это HDC).
Рисование Steam-буферов начинается с магического значения, за которым следует серия команд, идентифицированных 32-байтовым рынком. Вот поток, отправленный со специальным iframe при просмотре в Safari:
44727753 = 'DrwS' = DrawStream Magic
Командные буферы:
#0: 00000000 <SET TARGET>
3b01017a // Destination DC (hdc) *** Must match HDC in GdiDrawStream argument 1 ***
// Destination Clip (ERECTL):
0000011b // Left
00000011 // Top
0000012c // Right
0089f580 // Bottom *** Multiply by 2, and you get the "magic" value used in the iframe PoC ***
#1: 00000001 <SET SOURCE>
058506a3 // Source Surface (pso) *** Dumped the surface from kernel mode, got a 13x5 32BPP bitmap which is the Luna/Aero scrollbar slider control ***
#2: 00000009 <NINEGRID>
// Destination Clip (ERECTL): *** Should match the Destination Clip of the Target
0000011b // Left
00000011 // Top
0000012c // Right
0089f580 // Bottom
// Source Clip (ERECTL): *** Should be within the bounds of the surface (which is 13x5 in this case)
00000000 // Left
00000000 // Top
0000000e // Right
00000001 // Bottom
// NINEGRID_BITMAP_INFO *** Documented in RDP docs. Should fit within the surface and destination.
00000001 // Flags (DSDNG_STRETCH)
0000000a // Left Width
00000003 // Right Width
00000000 // Top Height
00000000 // Bottom Height
00000000 // Transparent
Вот сырая свалка:
0: kd> dds @r8 l18
00000000`003be664 44727753
00000000`003be668 00000000
00000000`003be66c 2b0108d5 // HDC, this will change from dump to dump
00000000`003be670 0000011b
00000000`003be674 00000011
00000000`003be678 0000012c
00000000`003be67c 0089f580
00000000`003be680 00000001
00000000`003be684 018503c2 // Bitmap Surface, this will change from dump to dump
00000000`003be688 00000009
00000000`003be68c 0000011b
00000000`003be690 00000011
00000000`003be694 0000012c
00000000`003be698 0089f580
00000000`003be69c 00000000
00000000`003be6a0 00000000
00000000`003be6a4 0000000e
00000000`003be6a8 00000001
00000000`003be6ac 00000001
00000000`003be6b0 0000000a
00000000`003be6b4 00000003
00000000`003be6b8 00000000
00000000`003be6bc 00000000
00000000`003be6c0 00000000
По сути, вы видите iframe, который имеет особенно интересную высоту, когда математическая ошибка в преобразовании NineGrid при рисовании и тематическом отображении полосы прокрутки вызывает запись "за пределами". Этот PoC будет работать в IE 8, но IE 8 имеет хорошо известную ошибку CSS, в которой он имеет максимальный предел пикселей (около 1342177), поэтому он не проявляется сразу.
ДРУГИЕ ВЫСОТЫ ВОЗМОЖНЫ, а некоторые могут быть достаточно маленькими, так что даже IE 8 попадает в угол высоты NineGrid.
IE9, по-видимому, вообще не управляет темами, использующими UxTheme, и его поведение полосы прокрутки отличается от IE 8, поэтому, несмотря на то, что ограничения по пикселям больше нет, PoC не работает. Firefox не был протестирован.
НЕ ТОЛЬКО УЛУЧШЕНИЯ. Тестирование с использованием HTML такой же высоты привело к сбою в Safari.
Это означает, что любой клиент, локальный или удаленный, который создает скины элементов управления (т. Е. Почти все из них - даже кнопка во флэш-PDF), может привести к преобразованию NineGrid, которое попадет в эту ошибку. Это совсем не специфично для WebKit.
Как примечание, MS недавно выпустила MS12-008, который исправляет это.