Книга: Разработка приложений в среде Linux. Второе издание
7.1. Код, содержащий ошибки
7.1. Код, содержащий ошибки
1: / * broken.с* /
2:
3: #include <stdlib.h>
4: #include <stdio.h>
5: #include <string.h>
6:
7: char global[5];
8:
9: int broken(void){
10: char *dyn;
11: char local[5];
12:
13: /* Для начала немного перезаписать буфер */
14: dyn = malloc(5);
15: strcpy(dyn, "12345");
16: printf ("1: %sn", dyn);
17: free(dyn);
18:
19: /* Теперь перезаписать буфер изрядно */
20: dyn = malloc(5);
21: strcpy(dyn, "12345678");
22: printf("2: %sn", dyn);
23:
24: /* Пройти перед началом выделенного с помощью malloc локального буфера */
25: * (dyn-1) ='';
26: printf ("3: %sn", dyn);
27: /* обратите внимание, что указатель не освобожден! */
28:
29: /* Теперь двинуться после переменной local */
30: strcpy(local, "12345");
31: printf ("4: %sn", local);
32: local[-1] = '';
33: printf("5: %sn", local);
34:
35: /* Наконец, атаковать пространство данных global */
36: strcpy(global, "12345");
37: printf ("6: %sn", global);
38:
39: /* И записать поверх пространства перед буфером global */
40: global[-1] = '';
41: printf("7: %sn", global);
42:
43: return 0;
44: }
45:
46: int main (void) {
47: return broken();
48: }
В этой главе мы рассмотрим проблемы в показанном выше сегменте кода. Этот код разрушает три типа областей памяти: память, выделенную из динамического пула памяти (кучи) с помощью malloc()
, локальные переменные размещенные в стеке программы и глобальные переменные, хранящиеся в отдельной области памяти, которая была статически распределена при запуске программы[9]. Для каждого класса памяти эта тестовая программа выполняет запись за пределами зарезервированной области памяти (по одному байту) и также сохраняет байт непосредственно перед зарезервированной областью. К тому же в коде имеется утечка памяти, что позволит продемонстрировать, как с помощью различных средств отследить эти утечки.
Несмотря на то что в представленном коде кроется много проблем, в действительности, он работает нормально. Не означает ли это, что проблемы подобного рода не важны? Ни в коем случае! Переполнение буфера часто приводит к неправильному поведению программы задолго до фактического его переполнения, а утечки памяти в программах, работающих длительное время, приводят к пустой растрате ресурсов компьютера. Более того, переполнение буфера является классическим источником уязвимостей безопасности, как описано в главе 22.
Ниже показан пример выполнения программы.
$ gcc -Wall -о broken broken.с
$ ./broken
1: 12345
2: 12345678
3: 12345678
4: 12345
5: 12345
6: 12345
7: 12345
- 3.2.4. Ошибки при задавании вопросов
- Ошибки проектирования базы данных
- 6.2. Типичные ошибки при проведении программ продвижения и варианты их устранения
- Дополнительные национальные кодовые страницы и порядки сортировки
- Глава 5 Агрессивные формы кода и борьба с ними
- Стиль написания исходного кода
- 1.4. Кодирование информации
- 1.4.1. Кодирование во время выполнения
- Три способа кодирования звука
- Листинг 15.11. Код для загрузки файла с Web-сервера
- 2. Пример создания базового отношения в записи на псевдокоде
- 5. Нормальная форма Бойса – Кодда (NFBC)