Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> вопрос по работе с overflow'льными ситуациями.. 
:(
    Опции темы
En_t_end
Дата 24.2.2006, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Товарищи... обьясните пожалуйста такую ситуацию(тривиально донельзя)
Код1
Код

#include "stdafx.h"

void main()
{
    using namespace std;
    char *buf = new char[201];
    try
    {
    strcpy(buf,"");
    for(unsigned int i = 0;i < 200+1000;i++)
        strcat(buf,"w");
    cout << buf << endl;
    }
    catch(...){
        cout << "buffer overflow!!!" << endl;}
}

Код2
Код

#include "stdafx.h"

void main()
{
    using namespace std;
    char *buf = new char[201];
//    try
//    {
    strcpy(buf,"");
    for(unsigned int i = 0;i < 200+1000;i++)
        strcat(buf,"w");
    cout << buf << endl;
//    }
//    catch(...){
//        cout << "buffer overflow!!!" << endl;}
}

Код3
Код

#include "stdafx.h"

void main()
{
    using namespace std;
    char buf[201];
    try
    {
    strcpy(buf,"");
    for(unsigned int i = 0;i < 200+1000;i++)
        strcat(buf,"w");
    cout << buf << endl;
    }
    catch(...){
        cout << "buffer overflow!!!" << endl;}
}

Очень позабавило то, что в Код1 можно выделить 201 байт, но юзать 1201 байт smile smile
Код2 аналогичен первому... но только подтверждает тот факт, что отлов исключений бессмыслен - всё и так нормально smile
А вот то что твориться в Код3 - это просто для меня невообразимо. Мало того, что выделяем в стеке 201 байт, юзаем 1201(именно так... хотя и системный отладчик выявляет buffer overrun - buf полностью(1200 w ровно) выводится в cout), НО И это по сути исключение не ловиться программно smile
Товарищи, я понимаю, что вопрос на пять копеек, что 1000 лишних байт можно поюзать без проблем(интересно в каком контексте они берутся ???), и что поюзать к примеру 10000 лишних байт уже не удастся(по крайней мере в моем примере мне не удалось), но всё же... что-то тут не так smile
PM MAIL ICQ Skype GTalk Jabber   Вверх
Partizan
Дата 24.2.2006, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 4
Всего: 67



что бы исключение произошло нужно сначало его выбросить....
читаем MSDN по strcpy()

Each of these functions returns the destination string.No return value is reserved to indicate an error.

там же:
These functions are deprecated because more secure versions are available; see strcpy_s, wcscpy_s, _mbscpy_s.

потому как strcpy видимо не следит за длиной строки....потому профилактикой переполнения при использовании таких функций приходится заниматься вручную....

если посмотреть предложенные в MSDN секурные функции то увидим:

Цитата

The strcpy_s function copies the contents in the address of strSource, including the terminating null character, to the location specified by strDestination. The destination string must be large enough to hold the source string, including the terminating null character. The behavior of strcpy_s is undefined if the source and destination strings overlap.






--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
MAKCim
Дата 24.2.2006, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

Товарищи, я понимаю, что вопрос на пять копеек, что 1000 лишних байт можно поюзать без проблем(интересно в каком контексте они берутся ???), и что поюзать к примеру 10000 лишних байт уже не удастся(по крайней мере в моем примере мне не удалось), но всё же... что-то тут не так

просто повезло, могло вылетить и раньше и позже, смотря в область каких данных ты писал


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
En_t_end
Дата 25.2.2006, 05:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Partizan
/*ИМХО
Дело не в этом... я понимаю, что strcat и strcpy - небезопасные функции. Меня интересует, почему !система! не определелила переполнение и разрешила писать в чужую область памяти. У меня вообще-то nt-система, в ней строго определены контексты процессов, нельзя взять память из чужой кучи или стека, по крайней мере вот таким образом. Получается, что Майкрософт заюзала в своей системе исключения,защищаемые ограниченные контексты процессов, но грамотно использовать их как всегда не смогла. То есть, пока системе не сообщат другие менеджеры памяти, что что-то не так с их контекстом она будет продолжать разрешать писать, пока не выброситься исключение - продолжаем писать, пока что-то... Пока рак на горе не свистнет... Почему мне нельзя выйти за границы массива операциями над указателями, а системе с её функциями можно ?, в итоге, я запускай порядка 10000 таких приложений(в цикле) получаю 10000000 байт ~10 мегабайт+-2мега самих приложений, а теперь порадуемся за ядро smile При ОЗУ в 64 мегабайта вероятность того, что я запишу что-то в область ядра, да и вообще в любую область 64-мег. ~ 16 %, что есть совсем неплохая вероятность.
*/
Далее, меня интересует, почему такие массивы грамотно выводятся вплодь до null-terminator ? Интересно, как же работают функции для поиска конца строки(а как ещё можно вывести "строку" ? smile) ? они наверное за null-terminator по всему контексту гоняются smile smile smile Да и ещё... char[] - это не связанный список, поэтому... smile
PM MAIL ICQ Skype GTalk Jabber   Вверх
chipset
Дата 25.2.2006, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Превед!
Цитата(En_t_end @ 24.2.2006, 19:59 Найти цитируемый пост)
Дело не в этом... я понимаю, что strcat и strcpy - небезопасные функции. Меня интересует, почему !система! не определелила переполнение и разрешила писать в чужую область памяти.


Это не чужая область, насколько я помню, для стека резервируеться какой-то обьем памяти.



Цитата(En_t_end @ 24.2.2006, 19:59 Найти цитируемый пост)
Почему мне нельзя выйти за границы массива операциями над указателями, а системе с её функциями можно ?,

Это проблемы стандарта Си а не системы, имхо.
Цитата(En_t_end @ 24.2.2006, 19:59 Найти цитируемый пост)
в итоге, я запускай порядка 10000 таких приложений(в цикле) получаю 10000000 байт ~10 мегабайт+-2мега самих приложений, а теперь порадуемся за ядро emo&:)endemo При ОЗУ в 64 мегабайта вероятность того, что я запишу что-то в область ядра, да и вообще в любую область 64-мег. ~ 16 %, что есть совсем неплохая вероятность.

При UB вообще есть вероятность того что ты отформатируешь C: smile Так что не парься, юзай std::string или напиши свой класс с проверкой на выход из границ.

Цитата(En_t_end @ 24.2.2006, 19:59 Найти цитируемый пост)
Интересно, как же работают функции для поиска конца строки(а как ещё можно вывести "строку" ? emo&:)endemo) ? они наверное за null-terminator по всему контексту гоняются emo&:)endemo emo&:)endemo emo&:)endemo


Именно так. Где-то внутри strlen приблизительно такой код:

Код

int strlen(char* a)
{
int i;
while(i++,a++);
return i;
}

В Паскале, к примеру, длина строки обозначаеться в самом первом байте и это рождает то самое ограничение в 255 байт ;)
Добавлено @ 07:55
Вот линк ффтему: http://www.joelonsoftware.com/articles/fog0000000319.html


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
En_t_end
Дата 25.2.2006, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



chipset,
Цитата(chipset @ 25.2.2006, 11:53 Найти цитируемый пост)
Это не чужая область, насколько я помню, для стека резервируеться какой-то обьем памяти.

Всё равно... ну не запишу я в чужую область памяти, но всё равно такой подход, даже не знаю, с чьей стороны(программиста или системы) губителен для процесса.
Ладно это стек, согласен, здесь скорее всего это не прокатит. Но как дело обстоит с кучей ?
Цитата(chipset @ 25.2.2006, 11:53 Найти цитируемый пост)
Так что не парься, юзай std::string или напиши свой класс с проверкой на выход из границ.

Я париться и не буду, я ведь тему создал, не для того, чтобы конкретную проблему решить smile просто хотелось бы всё острые углы проСЧупать... smile

За сЦылку спасибо!

Цитата(chipset @ 25.2.2006, 11:53 Найти цитируемый пост)
Именно так. Где-то внутри strlen приблизительно такой код:

Кстати... мы никак не сможем таким методом вылезти за sizeof(a) smile. А ведь в моем примере null-terminator лежит как раз за 1000 байт от sizeof(a) smile
Добавлено @ 09:09
Или всё таки char[] - в памяти - это связанный список ? smile Что-то мало вериться smile
PM MAIL ICQ Skype GTalk Jabber   Вверх
chipset
Дата 25.2.2006, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Цитата(En_t_end @ 24.2.2006, 23:07 Найти цитируемый пост)
Или всё таки char[] - в памяти - это связанный список ?

Как ты себе это представляешь? Указатель в конце каждого символа?
Цитата(En_t_end @ 24.2.2006, 23:07 Найти цитируемый пост)
Ладно это стек, согласен, здесь скорее всего это не прокатит. Но как дело обстоит с кучей ?

Зависит от параметров кучи.


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
En_t_end
Дата 25.2.2006, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



chipset,
Цитата(chipset @ 25.2.2006, 13:24 Найти цитируемый пост)
Как ты себе это представляешь? Указатель в конце каждого символа?

Я про то же... короче LOL smile
PM MAIL ICQ Skype GTalk Jabber   Вверх
Earnest
Дата 26.2.2006, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



En_t_end,
система следит за "большими" кусками памяти, выделенными VirtualAlloc. С ее точки зрения - весь Heap и весь стек - это куски памяти, принадлежащие твоему процессу.
А что там внутри - это CRT-код ведает... CRT - это наследие C, который никогда в жизни ничего не проверяет (чтобы побыстрее, значит). И слава богу.
Слишком жирно будет за каждым байтом следить... smile

Кстати, память с исполняемым кодом тоже где-то рядом... Туда запросто можно влезть, если вот так с буферами лихо работать...

Цитата(En_t_end @ 25.2.2006, 09:07 Найти цитируемый пост)
Кстати... мы никак не сможем таким методом вылезти за sizeof(a)

Еще как можем... ты же сам его затираешь, когда свои "W" туда пишешь...
sizeof(a) известен в единственном месте - в твоей функции main.



--------------------
...
PM   Вверх
En_t_end
Дата 27.2.2006, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Earnest,
Цитата(Earnest @ 26.2.2006, 23:27 Найти цитируемый пост)
Кстати, память с исполняемым кодом тоже где-то рядом... Туда запросто можно влезть, если вот так с буферами лихо работать...

...как страшно жить smile
Цитата(Earnest @ 26.2.2006, 23:27 Найти цитируемый пост)
Еще как можем... ты же сам его затираешь, когда свои "W" туда пишешь...
sizeof(a) известен в единственном месте - в твоей функции main.

То есть по сути, получается так... система резервирует какой-то кусок heap моему процессу. Далее её не волнует, что и как там твориться, единтственный хранитель драгоценной информации(кол-во байт на каждую переменную-обьект) - само же приложение. Поэтому записав за выделенную естественным путем память для конкретного массива мы просто напросто затираем нашу драгоценную информацию(в нашем же процессе), системе становиться пофигу и она выводит всю галиматью, что я успел скопировать, даже сверх нормы. В итоге процесс аварийно завершается, и система, которой на него по сути наплевать просто напросто отчищает именно тот выделенный участок heap.

Вывод: никогда не юзать несекурные функции(хотя с другой стороны, можно сэкономить пару тактов, если точно знать, что в массиве поместиться то, что туда ложиться).
Вывод2: увы при работе с памятью в контексте одного процесса можно вылезти без предупреждения за выделенную память, по крайней мере на несколько байт, однако результат будет весьма не забавен.

PM MAIL ICQ Skype GTalk Jabber   Вверх
Earnest
Дата 27.2.2006, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(En_t_end @ 27.2.2006, 16:56 Найти цитируемый пост)
То есть по сути, получается так... система резервирует какой-то кусок heap моему процессу. Далее её не волнует, что и как там твориться, единтственный хранитель драгоценной информации(кол-во байт на каждую переменную-обьект) - само же приложение. Поэтому записав за выделенную естественным путем память для конкретного массива мы просто напросто затираем нашу драгоценную информацию(в нашем же процессе), системе становиться пофигу и она выводит всю галиматью, что я успел скопировать, даже сверх нормы. В итоге процесс аварийно завершается, и система, которой на него по сути наплевать просто напросто отчищает именно тот выделенный участок heap.

Именно smile
Могу еще добавить, что если программа именно вывалится, да еще сразу за порчей памяти - считай, что тебе крупно повезло. Может быть запорчен кусок данных, которые просто используются в расчетах, и гадай себе, почему при сложении 2+2 получается то 5, то 8. А как только ставишь точку прерывания - чудо - все как в аптеке = 4!

Цитата(En_t_end @ 27.2.2006, 16:56 Найти цитируемый пост)
...как страшно жить

Переходить через дорогу тоже страшно, если хорошо подумать. А уж садится за руль - боже упаси! Столько вокруг уродов, пеших и конных...
Спасают рефлексы. В программировании то же самое. Вывод: накачивай рефлексы.



--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0971 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.