Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.012 c
1-74294
Delphi5.01
2003-10-11 23:33
2003.10.23
WordDocument1.Range.Find.Execute


3-74051
ALFA
2003-10-02 15:37
2003.10.23
ПЕРЕКОДИРОВКА


14-74417
_Nicola_
2003-10-06 17:45
2003.10.23
Старое техно - MAXX


1-74292
Chuha
2003-10-12 21:24
2003.10.23
listbox


1-74213
Костик
2003-10-09 21:36
2003.10.23
Форматирование таблицы формата Excel





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский