В случае целочисленных переполнений, что является результатом (unsigned int) * (int)? без знака или int? - PullRequest
8 голосов
/ 06 апреля 2009

В случае целочисленных переполнений, что будет результатом (unsigned int) * (int)? unsigned или int? Какой тип оператор индекса массива (operator[]) принимает за char*: int, unsigned int или что-то еще?

Я проверял следующую функцию, и вдруг возник этот вопрос. У функции есть уязвимость в строке 17.

// Create a character array and initialize it with init[] 
// repeatedly. The size of this character array is specified by 
// w*h.
char *function4(unsigned int w, unsigned int h, char *init)
{
    char *buf;
    int i;

    if (w*h > 4096)
        return (NULL);

    buf = (char *)malloc(4096+1);
    if (!buf)
        return (NULL);

    for (i=0; i<h; i++)
        memcpy(&buf[i*w], init, w);  // line 17

    buf[4096] = '\0';

    return buf;
}

Рассмотрим w и h очень большие целые числа без знака. Умножение в строке 9 имеет шанс пройти проверку.

Теперь проблема в строке 17. Умножьте int i на unsigned int w: если результат равен int, возможно, что продукт отрицательный, что приведет к получению доступа к позиции, которая находится до buf. Если результат равен unsigned int, продукт всегда будет положительным, что приведет к доступу к позиции после buf.

Трудно написать код, чтобы оправдать это: int слишком велик. У кого-нибудь есть идеи по этому поводу?

Есть ли какая-либо документация, в которой указан тип продукта? Я искал его, но пока ничего не нашел.

Я полагаю, что с точки зрения уязвимости, (unsigned int) * (int) производит unsigned int или int, не имеет значения, потому что в скомпилированном объектном файле они являются просто байтами. Следующий код работает одинаково независимо от типа продукта:

unsigned int x = 10;
int y = -10;

printf("%d\n", x * y);  // print x * y in signed integer
printf("%u\n", x * y);  // print x * y in unsigned integer

Следовательно, не имеет значения, какой тип возвращает умножение. Имеет значение то, принимает ли функция потребителя int или unsigned.

Вопрос здесь , а не , насколько плоха функция или как ее улучшить, чтобы сделать ее лучше. Функция, несомненно, имеет уязвимость. Речь идет о точном поведении функции, основанном на предписанном поведении стандартов.

Ответы [ 13 ]

0 голосов
/ 06 апреля 2009

Чтобы на самом деле ответить на ваш вопрос, без указания оборудования, на котором вы работаете, вы не знаете, и в коде, предназначенном для переносимости, вы не должны зависеть от какого-либо конкретного поведения.

0 голосов
/ 06 апреля 2009

memcpy (& buf [i w> -1? I w <4097? I <em>w: 0: 0], init, w); Я не думаю, что тройное вычисление i w ухудшает производительность)

0 голосов
/ 06 апреля 2009

Почему бы просто не объявить меня как int без знака? Тогда проблема исчезнет.

В любом случае, i * w гарантированно будет <= 4096, так как код проверяет это, поэтому он никогда не будет переполнен. </p>

...