Некорректное чтение / запись иногда создает ошибку сегментации, а иногда нет - PullRequest
2 голосов
/ 27 декабря 2011

Пример кода:

int main ()
{
  char b[] = {"abcd"};
  char *c = NULL;
  printf("\nsize: %d\n",sizeof(b));
  c = (char *)malloc(sizeof(char) * 3);
  memcpy(c,b,10);   // here invalid read and invalid write
  printf("\nb: %s\n",b);
  printf("\nc: %s\n",c);

  return 0;
}

Смотрите в коде, я сделал несколько недопустимых операций чтения и недопустимых операций записи, но эта небольшая программа прекрасно работает и не создает core dump.

Но однажды в моей большой библиотеке, когда я делаю 1 байт неверного чтения или неправильной записи, он всегда создавал дамп ядра.

Вопрос:

Почему я иногда получаю дамп ядра из-за неправильного чтения / записи, а иногда не получаю дамп ядра?

Ответы [ 3 ]

6 голосов
/ 27 декабря 2011

Это полностью зависит от того, что вы перезаписываете или разыменовываете, когда делаете неверное чтение / запись. В частности, если вы перезаписываете некоторый указатель, который разыменовывается, например, скажем, самый старший байт одного, вы можете получить разыменование чего-либо в совершенно другой (и совершенно недействительной) области памяти.

Так, например, если стек был упорядочен таким образом, что memcpy после конца c перезаписывал бы часть b, когда вы пытаетесь вызвать printf() с b в качестве аргумента, он пытается возьмите этот указатель и разыщите его, чтобы напечатать строку. Так как он больше не является действительным указателем, это вызовет segfault. Но поскольку такие вещи, как расположение в стеке, зависят от платформы (и, возможно, от компилятора?), Вы можете не увидеть одинаковое поведение с похожими примерами в разных программах.

5 голосов
/ 27 декабря 2011

То, что вы пытаетесь сделать, это в основном переполнение буфера и в вашем примере кода более конкретно переполнение кучи .Причина, по которой вы видите сбой только время от времени, зависит от того, к какой области памяти вы обращаетесь, и если у вас есть разрешение на доступ к ней / запись (что было хорошо объяснено Дэном Фего).Я думаю, что пример, представленный Дэном Фего, больше касается переполнения стека (исправление приветствуется!).У gcc есть защита, связанная с переполнением буфера в стеке (разрушение стека).Это можно увидеть (переполнение стека) в следующем примере:

#include <stdio.h>
#include <string.h>

int main (void)
{
    char b[] = { "abcdefghijk"};
    char c [8];
    memcpy (c, b, sizeof c + 1);      // here invalid read and invalid write
    printf ("\nsize: %d\n", sizeof b); 
    printf ("\nc: %s\n", c); 
    return 0;
}

Пример вывода:

$ ./a.out 

size: 12

c: abcdefghi���
*** stack smashing detected ***: ./a.out terminated

Эту защиту можно отключить с помощью параметра -fno-stack-protector в gcc.
Переполнение буфера является одной из основных причин уязвимости безопасности.К сожалению, такие функции, как memcpy, не проверяют наличие подобных проблем, но есть способы для защиты от подобных проблем.
Надеюсь, это поможет!

0 голосов
/ 27 декабря 2011

вы создаете строку из 3 символов c, но копируете в нее 10 символов. это ошибка.

это называется переполнением буфера: вы пишете в память, которая вам не принадлежит. поэтому поведение не определено. это может быть сбой, он может нормально работать или изменить другую созданную вами переменную.

так что самое главное - выделить достаточно памяти для c, чтобы вместить содержимое b:

c = (char *)malloc(sizeof(char) * (sizeof(b)+1)); // +1 is for the '\0' char that ends every string in c.

2 - при копировании b в c не забудьте поставить конец строки char: '\0'. это обязательно в стандарте c. поэтому printf("%s",c); знает, где заканчивать строку.

3 - вы скопировали 10 символов из b в c, но b содержат только 5 символов (a, b, c, d и '\ 0'), поэтому поведение memcpy не определено ( Например: memcpy может попытаться прочитать память, которая не может быть прочитана, ...).

Вы можете скопировать только ту память, которая у вас есть: 5 символов b.

4 - я думаю, что хорошая инструкция для определения b: char b="abcd"; или char b={'a','b','c','d',0};

...