﻿# Проблемы 64\-битного кода в реальных программах: а что же Linux?

Рассказывая про 64\-битные ошибки, поджидающие программистов при миграции их программ, я часто слышу упреки: "Ну да, этот ваш Windows, он такой\.\.\. Хорошо, что в Linux с 64\-битным кодом проблем да\-а\-а\-авно уже нет"\.

"А вот и нет, мой любознательный читатель"\. Сегодняшний пост про 64\-битную ошибку  в ядре Linux\.  Чудесный сайт с системой отслеживания  ошибок \(bug tracking system\) разработчиков ядра содержит описание [bug 16603](https://bugzilla.kernel.org/show_bug.cgi?id=16603) \(send of data \> 4 GB fails on 64 bit systems\)\. Суть проблемы проста: "Отправка  данных с использованием Linux\-функции send\(\) приводит к ошибке, если размер данных слишком большой\. Функция из glibc выглядит так:

```cpp
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
```

Все корректно, размер передается как memsize\-тип [size\_t](https://pvs-studio.ru/ru/blog/terms/0044/)\. Однако этот аргумент сохраняется в структуре msgheader, после чего внутри функции tcp\_sendmsg идут строки:

```cpp
while (--iovlen >= 0) {
                int seglen = iov->iov_len;
                unsigned char __user *from = iov->iov_base;
```

Здесь длина уже сохраняется в int, что, конечно же, никуда не годится\. То есть отправка с помощью send\(\) блока в 5 гигабайт приведет к отправке только 1 гигабайта, а отправка блока в 4 гигабайта не даст ничего \(из\-за "округления" до нуля\)\.

Конечно, workaround понятен – указывать длину не более 0x8000000, но это ошибка и конечно же ее надо править\. 

Да, и это не из девяностых пример\. Баг открыт в августе 2010 года, относится к ядру версии 2\.5\. И пока \(11 октября 2010\) не закрыт\.  А вы говорите в Linux 64\-битных проблем нет\.\.\.