Форум: "Основная";
Текущий архив: 2003.10.23;
Скачать: [xml.tar.bz2];
ВнизПереполнение массива в длл Найти похожие ветки
← →
yaJohn (2003-10-09 11:19) [0]Есть доволе странная ситуация: вызываю функцию из чуждой ДЛЛ с двумя параметрами: integer по значению и буфер по ссылке, тобишь указатель.
По возвращении из функции переменная содержавшая integer параметр (переданный по значению) меняет свое значение... Только не говорите мне что так не бывает. Я до вчерашнего вечера тоже так думал.
После долгих размышлений пришел к следующему:
обе переменные обьявленны в классе, нечто вроде
TMyClass = class
....
MyArray: array [0..1000] of byte;
MyVar: integer;
....
Видимо, длл-функция лезет за край массива (хотя не должна). Предположим, действительно криво написана длл. Теперь вопрос:
Как обьявить статический массив, чтобы при попытке выйти за диапазон генерились страшные экзепшены и акссес виолейшены.
Нет, при попытке сказать MyArray[1001] или иже с ним все нормально, экзепшн есть. Но длл, видимо не так щепетильна в проверке диапазонов.
← →
Digitman (2003-10-09 11:27) [1]скорей всего ты просто нарушил соглашение о бызовах для данной DLL ... она ж "чужая", док-ции нет, и ты от балды проставил соглашение)
← →
TUser (2003-10-09 11:29) [2]может так
var
firstArray[..], secondArray[..];
//2 массива одного размера
begin
Func(Int, FirstArray);
try
Second:=First;
except
end;
Хотя памяти много надо.
← →
Digitman (2003-10-09 11:35) [3]
> Как обьявить статический массив, чтобы при попытке выйти
> за диапазон генерились страшные экзепшены и акссес виолейшены.
>
никак.
вернее - как угодно.
для ОС совершенно индифферентно как ты его объявишь
AV генерируется при выходе не за пределы какого-то там массива, а при нарушении прав доступа к странице памяти в ВАП процесса
> Но длл, видимо не так щепетильна в проверке диапазонов
никаких "диапазонов" DLL не проверяла и проверять никогда не будет , если не используются соотв. спец.опции соответствующего компилятора (использованного при создании DLL) и декларация диапазонного типа не соответствует соглашениям данного компилятора по автоматически генерируемого кода проверок
← →
yaJohn (2003-10-09 11:41) [4]2> Digitman
В этой длл юзается еще два десятка функций. Вполне успешно. Функция переполняющая массив в принципе тоже дает верные результаты.
Что такое stdcall я тоже в курсе. Соглашение о вызовах - это первое что я проверил. А потом перепроверил. Документацию по длл я читал.
2 TUser
Память не критична. Мне скорее надо однозначно идентефицировать проблему. Желательно с уликами и доказательствами. Дабы потом настучать по мозгам авторам длл.
Можно попробовать решить проблему в лоб, увеличением буфера, но кто скажет, при каких условиях н хватит "раздутого" буфера?
Для справки - длл из API к хитрому PCI девайсу (АЦП). Писана фирмой производящей девайсы.
← →
HolACost! (2003-10-09 11:45) [5]Есть хороший и вполне хорошийе 2 выхода!!!!!
1 - перебором... автоматическим
2 - дезассемблировать и проверить сколько она юзает! Там тебе и доказательства будут налицо!!!!
← →
Digitman (2003-10-09 11:49) [6]
> Соглашение о вызовах - это первое что я проверил
каким образом ? ты дизассемблировал эту библиотеку или методм научного тыка искал соглашение ?
← →
yaJohn (2003-10-09 11:49) [7]>для ОС совершенно индифферентно как ты его объявишь
Спорное утверждение. Но это не важно. Зададим вопрос по другому:
как получить буфер (от дельфи, системы, черта) чтобы любое обращение за его пределы вызывало однозначную ошибку.
>никаких "диапазонов" DLL не проверяла и проверять никогда не будет
То что длл не проверяет диапазоны я уже понял. Само по себе это не есть хороший стиль. Но еще не ошибка.
← →
han_malign (2003-10-09 11:54) [8]>integer по значению и буфер по ссылке
- уверен, что по значению? Как функция объявлена?
← →
yaJohn (2003-10-09 11:58) [9]2 Digitman
Сударь, Вы встали не с той ноги? Соглашение о вызовах я определил путем чтения документации. По описанным выше симптомам я тоже первым делом подумал о соглашениях. Поэтому не мудрствуя лукаво перебрал все возможные варианты. Со всей ответственностью могу заявить, что соглашения о вызовах здесь ни при чем.
← →
Anatoly Podgoretsky (2003-10-09 12:00) [10]Метод научного втыка не очень эффективный
← →
Anatoly Podgoretsky (2003-10-09 12:01) [11]yaJohn © (09.10.03 11:58) [9]
Вот и приведи его здесь, зачем же остальным заниматься телепатией, только точно из документации, а не из головы, с поисанием параметров.
← →
Digitman (2003-10-09 12:01) [12]
> yaJohn
> Спорное утверждение
да никакого спора ! именно так и не иначе !
в ран-тайм при выполнении маш.инструкции обращения к участку вирт.памяти никаких "массивов" уже не существует.
существуют страницы вирт.памяти в АП процесса, и каждая из этих страниц имеет соотв.атрибуты/привелегии доступа.
если инструкция, обращающаяся по адресу в такой-то странице, нарушает тем или иным образом права доступа к этой странице, происходит GPF, следствием которого является прерывание по нарушению доступа, и в конечном итоге, AV-исключение. Весьма упрощенно, конечно, это описано мной ...
> как получить буфер (от дельфи, системы, черта) чтобы любое
> обращение за его пределы вызывало однозначную ошибку.
просто передай в кач-ве адреса буфера nil
если в теле вызываемой ф-ции нет соотв.проверки на nil, AV тебе гарантировано !
> То что длл не проверяет диапазоны я уже понял. Само по себе
> это не есть хороший стиль
строго наоборот
если DLL отлажена, то нет никакого резона перед распространением ее окончательного релиза компилировать ее с опциями проверки диапазонов. Кому , спрашивается, нужно бестолковое снижение производительности библ-х ф-ций из-за избыточного кода проверок ?
← →
Digitman (2003-10-09 12:03) [13]с той или не с той - неважно)
если ты действительно владеешь док-цией к DLL, приведи дословно ее фрагмент, где описывается декларация проблемного эксп.вызова
← →
Digitman (2003-10-09 12:07) [14]и далее.
если это действительно stdcall, лишний раз не помешает убедиться в этом, при том что ты сомневаешься в корректности реализайии ф-ции
дизассемблируешь ф-цию, ищешь в ее листинге все возвраты из п/п и убеждаешься как минимум в том, что они выглядят как RET 8
← →
yaJohn (2003-10-09 12:14) [15]BOOL ReadInfoBlock(
HANDLE hID,
LPVOID lpBuffer
);
← →
Anatoly Podgoretsky (2003-10-09 12:22) [16]Оп, тогда с чего ты решил, что размер буфера для данной функции равен 1001. Приведи и этот кусок документации. Потом аналогично насчет hID, ты то что нужно передаешь. Про соглашение об вызове я молчу, здесь вообще нет этой информации.
← →
Digitman (2003-10-09 12:29) [17]заодно приведи свой Паскаль-адаптированный вариант этой декларации и фрагмент вызова ф-ции
← →
han_malign (2003-10-09 12:33) [18]Насколько я знаю такого стиля API, либо lpBuffer имеет фиксированную структуру и первое поле у него cbSize(стиль Microsof для совместимости версий, в TAPI, для всех структур переменного размера - три первых поля dwTotalSize, dwNeededSize, dwUsedSize) , либо существует дополнительная функция, типа GetInfoBlockSize, и ты должен гарантировано выделить требуемый размер...
А самонадеянно использовать, самолично придуманный, фиксированный размер - это криминал.
← →
nikkie (2003-10-09 12:37) [19]>han_malign
либо в документации написано что-то вроде
This buffer must be at least MAX_PATH characters in size.
криминал, это точно.
← →
yaJohn (2003-10-09 14:01) [20]Я могу привести примеры кода, цитаты из документации и пр. Но я не прошу найти у меня ошибки! Я и так знаю где они. В ДНК, в стиле программирования, в самонадеяной и кримональной любви к числу 1001, в том что я вообще решил занятся этим ремеслом, в английском (устном и письменном), в формулировках вопросов и т.д. Я не разумею ни альфы ни омеги вин-апи и с соглашениями (декларативными и психологическими) у меня трудности с детства. Мои программы работают только за счет взаимокомпенсации ошибок и фантастической стойкости масдая и борландов к бредовому коду. Я со всем этим согласен заранее и навсегда.
А теперь мне очень хотелось бы узнать, можно ли (и если да то как) создать буфер, такой чтобы при любом (с 3 кольца) обращении (через указатель на оный буфер) за его границы происходило нечто специфическое (например AV), позволяющее утверждать, что это была именно попытка переполнения буфера.
Заранее спасибо.
← →
Digitman (2003-10-09 14:49) [21]
> Я могу привести примеры кода, цитаты из документации и пр
тебя, видимо, на коленях надо упрашивать это сделать)
> можно ли
да можно, можно ! но не нужно)
ну зачем ты себе проблемы ищешь там где их нет ?
сильно смахивает все это на бородатый анекдот про мужика, изрядно поддавшего, который ищет потеряный кошелек не там где потерял, а возле фонарного столба, с безапелляционной и убивающей наповал мотивировкой - мол, здесь светлее)
ну зачем его создавать, этот буфер ?
вариант 1:
берешь на вооружение любой более-менее серьезный дебаггер (подойдет и старенький TD32), ставишь аппаратные брейкпойнты в сомнительные точки за пределами диапазона адресов массива (с условием останова при чтении/записи), ловишь брейкпойнты и смотришь адрес инструкции, пытавшейся получить доступ .. если твое предположение подтвердится, то адрес инструкции будет лежать в диапазоне адресов, занимаемых модулем DLL
вариант 2:
средствами обычного дельфийского встроенного дебаггера просто трассируешь в окне CPU инструкции, исполняемые в ходе вызова проблемной ф-ции
дебаггер же - первый друг программера ! неужто в 1-й раз слышишь !?)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.10.23;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.011 c