Not a kernel guy

… in the Windows kernel team

Tuesday, March 6, 2007

/LARGEADDRESSAWARE может испортить вам весь день.

Только что потратил кучу времени на разборки с /LARGEADDRESSAWARE. Этот ключ используется для указания сборщику, что данный модуль (.exe или .dll) способен корректно обрабатывать адреса больше 2GB. Модули, помеченные подобным образом, могут быть загружены выше 2GB при условии, что система поддерживает увеличенное пользовательское адресное пространство. На данный момент это либо серверные версии Windows, сконфигурированные ключом /3GB в boot.ini, либо 64-х битные версии системы.

Про причины того, почему расширенное адресное пространство не включается для всех программ, хорошо написал Raymond Chen: Myth: The /3GB switch expands the user-mode address space of all programs. Дело как всегда в том, что слишком много приложений не будут работать в такой конфигурации - начинает буксовать арифметика указателей. Сегодняшний баг занёс ещё одну операцию в “черный” список.

Итак, какое значение будет присвоено переменной wide_ptr после инициализации (код компилируется для x86)?

PVOID ptr = (PVOID)0x87654321;
ULONGLONG wide_ptr = (ULONGLONG)ptr;

Ответ - 0xffffffff87654321! Очевидно, что проблема в расширении знака, однако это совсем не очевидно из данного отрывка кода. Чтобы результат получился верным, код нужно переписать вот так:

PVOID ptr = (PVOID)0x87654321;
ULONGLONG wide_ptr = (ULONGLONG)(ULONG_PTR)ptr;
Posted at 12:39 pm •

RSS feed | Trackback URI

6 Comments »

Comment by Wesha — March 7, 2007 @ 9:10 am

Я думаю, расстрелять надо того @удака, который н-дцать лет назад сделал указатели signed.

 
Comment by Not a kernel guy — March 7, 2007 @ 9:26 am

Если б каждого такого расстреливать - сколько бы народу полегло! :-)

 
Comment by Wesha — March 7, 2007 @ 4:56 pm

А заодно еще и того, кто придумал иметь общий стек на адреса возврата и временные данные (и тем самым породил проблемы с переполнением буфера).
Кстати, совершенно не понимаю, почему современные компилерам не делают раздельные стеки. Тем самым проблема переполнения решается на 95% простой перекомпиляцией программы.

 
Comment by Not a kernel guy — March 7, 2007 @ 5:22 pm

 

Кстати, совершенно не понимаю, почему современные компилерам не делают раздельные стеки.

Подозреваю, что из-за проблем с совместимостью и производительностью:

  1. Поломаются все существующие средства отладки. Да и существующим API, тому же Win32, не поздоровится;
  2. Из-за раздельных стеков придется все время либо перегружать esp, либо выделять отдельный регистр для второго стека, либо эмулировать второй стек вручную. В любом случае получается медленно.
 
Comment by Wesha — March 9, 2007 @ 9:33 am

У всех свои недостатки (с) Во-первых, как-то смешно говорить о десятке лишних инструкций на системный вызов при процессорах о трех гигагерцах, а во-вторых, раз программу все равно перекомпилировать, то вполне можно иметь #define SAFE_STACK, по которому системные вызовы и будут все понимать.

По-моему, все же лучше слегка пожертвовать производительностью, чем потом закрывать туеву хучу дырок постфактум. Проверка длины буфера - это, похоже, sacred knowledge, известное в основном только нашим программерам.

P.S. У твоего блога сносит крышу, если коммент содержит кавычки или апострофы. Которые еще и эскейпятся криво. Похоже, вы там чего-то намудрили с защитой от sql injection.

 
Comment by Not a kernel guy — March 9, 2007 @ 10:43 am

 

Во-первых, как-то смешно говорить о десятке лишних инструкций на системный вызов при процессорах о трех гигагерцах

Не на системный вызов. На вызов любой функции. Если функция обращается к стеку данных, значит понадобится дополнительный код, обслуживающий обращения к стеку данных.

По-моему, все же лучше слегка пожертвовать производительностью

Скорее всего производительность не будет основной проблемой. Вот совместимость - это да. Она будет такой проблемой, что мало не покажеться. Хотя, если подумать, .NET (или Java), по сути, и является решением, которое как раз и родилось в результате попыток сделать компилируемый код безопаснее. Заодно и проблему совместимости обошли. :-)

У твоего блога сносит крышу

Значит пришла пора перейти на версию посвежее: http://trac.wordpress.org/ticket/2761. :-)

 

Your Comment (smaller | larger)

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Powered by WordPress