Чтение стека памяти - PullRequest
1 голос
/ 10 октября 2008

Со следующим фрагментом кода:

typedef struct
{
    char    fileName[ 1024];
    time_t  deleteTime; 
} file_item_t;

....
....

setEntry(char *fileName)
{
    file_item_t     file;

    memset( &file, 0x00, sizeof( file_item_t ));

    memcpy( file.fileName, 
         fileName, 
         sizeof( file.fileName ) - 1 );
...
...

Когда эта функция вызывается, она работает нормально на машине SPARC, но происходит сбой на i386, работающих под управлением Solaris 10. fileName это строка с нулевым символом в конце, скажем, около 30 символов. Похоже, что попытка чтения за пределами диапазона fileName с использованием memcpy() вызывает ошибку сегментации в некоторых системах.

Это устаревший код, который легко исправить. Но то, что я хотел бы знать, о базовых характеристиках, которые могут привести к этому провалу или нет. Это связано с нарушением чтения в стеке? Какой-то переход границы? Это связано с сегментацией памяти и является случайностью (в зависимости от того, как сегментация / разбиение памяти выполняется управлением памятью и ОС), что он может дать сбой или нет.

Ответы [ 3 ]

5 голосов
/ 10 октября 2008

Вы уже ударили ногтем по голове:

В вашем memcpy вы читаете больше длины имени файла.

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

Очевидное решение - использовать strcpy или strncpy.

1 голос
/ 10 октября 2008

С учетом предоставленной информации мы не знаем, куда указывает аргумент char *filename - стек, куча, раздел данных или другое ...

Если он находится в стеке, это может быть связано с тем, что размер стека по умолчанию в SPARC намного больше, чем в x86, и растет намного выше. С помощью SPARC ABI в стековом фрейме всегда есть место для резервного копирования всех 16 регистров, плюс место для шести параметров, если функция принимает какой-либо (даже если он требует меньше). Поэтому SPARC потребляет не менее 64 или 92 байта стека на вызов функции, тогда как x86 может обходиться только 8 или 4 байтами на вызов функции.

Если он находится в куче или в разделе данных, то может случиться так, что среда выполнения (куча) или компилятор (данные) поместят строку в конец страницы на x86, поэтому запускать конечные результаты при чтении плохой памяти.

1 голос
/ 10 октября 2008

Вы уверены, что строка, на которую указывает fileName, действительно имеет длину 1024 байта? Мне почему-то кажется, что вы должны использовать strcpy вместо memcpy.

Если fileName короче, memcpy копирует байты за настоящими строковыми данными и, вероятно, вызовет нарушение прав доступа при чтении этой памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...