Это вызовет переполнение? - PullRequest
0 голосов
/ 02 февраля 2011

У меня есть следующий фрагмент кода, и я думаю, что это может вызвать переполнение в функции readlink ().

pid_t get_pid_from_proc_self()
{
    char buffer[4];
    pid_t pid;

    readlink("/proc/self", buffer, sizeof(buffer));

    sscanf(buffer, "%d",(int *)&pid);

    return pid;
}

Поскольку PID в Linux составляет 4 байта, readlink() копирует 32 бита из "/ proc / self" в target[]. Тогда, по моему мнению, для '\0' должен использоваться дополнительный байт, что составляет 5 байтов.

Кроме того, readlink() автоматически вставляет '\0' в конец строки, или мне нужно специально назначить ее последнему байту?

Ответы [ 5 ]

3 голосов
/ 02 февраля 2011

Нет, это не приведет к переполнению. Он прочитает не более sizeof(buffer) байтов, а затем остановится. Он не завершает вашу строку нулем, так что вам придется это сделать. Чтение buffer до подтверждения того, что последний байт равен \0, приведет к неопределенному поведению (что и делает ваш sscanf() вызов).

2 голосов
/ 02 февраля 2011

По приведенным здесь примерам:

http://pubs.opengroup.org/onlinepubs/009695399/functions/readlink.html

if ((len = readlink("/modules/pass1", buf, sizeof(buf)-1)) != -1)
    buf[len] = '\0';

Edit:

Интересно о:

Поскольку PID в Linux составляет 4 байта, readlink () копирует 32 бита из "/ proc / self" ...

Разве вы не возвращаете строковую версию PID, а не фактическое 4-байтовое целое число? Может ли ваше значение быть до 10 цифр? 5 цифр? (за комментарий о том, что максимальное значение процедуры намного меньше, чем максимальное 4-байтовое значение int - спасибо @Karl)

1 голос
/ 03 февраля 2011

Ваше предположение совершенно не соответствует действительности.Значение sizeof(pid_t), равное 4, не означает, что для хранения десятичной строки , представляющей число, требуется 4 байта.Типичный 16-разрядный pid, такой как 12345, очевидно, требует 6 байтов для хранения в виде строки, и, если Linux настроен на разрешение более 32768 процессов, он может легко быть длиннее.

Правильный размер буфера дляудерживайте целочисленный тип foo_t в качестве десятичной строки 3*sizeof(foo_t)+2.Если хотите, вы можете немного улучшить границы, но я не против потратить несколько байтов на простоту (и очевидную правильность) в источнике.

(Обратите внимание, что я предполагаю 8-битные байты, который требуется POSIX, так как pids - это концепция POSIX. Если вы хотите поддерживать большие байты, вам нужно адаптировать границу, используя CHAR_BIT.)

1 голос
/ 02 февраля 2011

readlink() не вызовет переполнения, но не добавит завершающий \0, а sscanf() может сильно повредить (переполнение буфера).Из справочной страницы readlink().

readlink () помещает содержимое пути символьной ссылки в буфер buf, который имеет размер bufsiz.readlink () не добавляет нулевой байт в buf.Он будет обрезать содержимое (до длины символов bufsiz), если буфер слишком мал, чтобы вместить все содержимое.

Кроме того, readlink() читает текст PID, которыйможет быть больше "9999".Использование только четырех байтов для хранения значения PID в тексте недостаточно.

1 голос
/ 02 февраля 2011

readlink не будет переполнен, потому что он не ставит '\ 0' в конце. Но сканф будет. Вы должны сделать это:

Вы должны сделать это:

char buf[5];
ssizet_t len;
...
if ((len = readlink("/proc/self", buf, sizeof(buf)-1)) != -1)
    buf[len] = '\0';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...