LINUX.ORG.RU
ФорумTalks

MIN_INT / -1

 


2

2

Поискал по форуму, кажется, эта тема еще не обсуждалась.

После нескольких веселых дыр в рельсах и свежей дыры в макоси, вот еще одна эпичная дырка, которая сейчас обсуждается в рунете. При том она особенно эпична тем, что затрагивает не конкретное ПО, а неограниченно широкий класс программ.

!Ъ:
http://avva.livejournal.com/2548306.html
http://users.livejournal.com/_winnie/375276.html

Ъ:

Прикольно - оказывается, инструкция idiv, деление со знаком, на x86 кидает исключение не только при делении на ноль, но и когда результат не помещается в регистр. А этого очень легко добиться, написав в C например INT_MIN / -1. Как мы помним, INT_MIN по модулю на единицу больше, чем INT_MAX; например, в 32-битных числах INT_MIN равно -2147483648, а INT_MAX равно 2147483647. Поэтому когда INT_MIN делят на -1, положительный результат не вмещается в 32 бита.

Само по себе это не катастрофа - ну кидает исключение, ну и подумаешь. Дело в том, однако, что про деление на ноль все знают и помнят, и проверяют перед попыткой делить. А против INT_MIN/-1 никто практически не защищается. Поэтому можно, например:

- крэшнуть компилятор (правда, игрушечный), PostgreSQL (не игрушечную) или антивирус;
- подвесить Windows 8;
- убить bash

★★

Последнее исправление: geekless (всего исправлений: 1)

Ответ на: комментарий от tazhate

Я чего-то не понимаю?

Да. На x86_64 будет другое значение INT_MIN, и результат, соответственно, точно так же не впишется в 64 бита.

geekless ★★
() автор топика
Ответ на: комментарий от tazhate

например, в 32-битных числах INT_MIN равно -2147483648, а INT_MAX равно 2147483647. Поэтому когда INT_MIN делят на -1, положительный результат не вмещается в 32 бита.

Вероятно.

buddhist ★★★★★
()
Ответ на: комментарий от geekless

Да. На x86_64 будет другое значение INT_MIN, и результат, соответственно, точно так же не впишется в 64 бита.

А, понял. Спасибо.

tazhate ★★★★★
()

>деление со знаком, на x86 кидает исключение не только при делении на ноль, но и когда результат не помещается в регистр

:[|||||||||||||||||||||||||||||||||||||||||||||||||]:

luke ★★★★★
()
$ ($((-2**63/-1)))
bash: -9223372036854775808: команда не найдена
$ bash --version
GNU bash, version 4.2.37(1)-release (i486-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
AITap ★★★★★
()
Ответ на: комментарий от tazhate

В bash уже починили. В busybox sh воспроизводится.

geekless ★★
() автор топика
Ответ на: комментарий от abraziv_whiskey

Читали-то многие. Я, например, в спеках интела читал. А помнят - не многие. Я вот начисто забыл.

geekless ★★
() автор топика

главно шоб этотже баг не вылез в java

Deleted
()

А еще прикольный эффект от INT_MIN * -1

#include <limits.h>
#include <stdio.h>

volatile int x = -1;
volatile int y = INT_MIN;
volatile int z = 0;
int main() {
    z = y * x;
    printf("%d\n", z);
    return 0;
}

$ gcc -o test test.c 
$ ./test 
-2147483648
Vovka-Korovka ★★★★★
()
Ответ на: комментарий от xtraeft

какой эффект? у меня баш повис вроде

У меня тупо вылетает сам баш.

taz@think ~ $ bash
taz@think ~ $ echo $((-2**63/-1))
Исключение в операции с плавающей точкой
taz@think ~ $

tazhate ★★★★★
()

gcc в курсах

$ gcc -o test test.c 
test.c: В функции «main»:
test.c:4:17: предупреждение: переполнение при вычислении целочисленного выражения [-Woverflow]
$ ./test
$
redgremlin ★★★★★
()
Ответ на: комментарий от tazhate
echo $((-2**31/-1))
2147483648
bash --version
GNU bash, версия 4.2.37(2)-release (i586-mandriva-linux-gnu)
redgremlin ★★★★★
()
Ответ на: комментарий от xtraeft

ага, у меня тоже вылетел, но не перезапустился

У меня тоже ничего не перезапускалось.

tazhate ★★★★★
()
Ответ на: комментарий от xtraeft

гы, у меня оказывается

GNU bash, version 3.2.48(1)-release

с новым:

bash-4.2$ echo $((-2**63/-1))
Floating point exception: 8

xtraeft ★★☆☆
()
Ответ на: gcc в курсах от redgremlin

Это если статически отследить можно.

buddhist ★★★★★
()
Ответ на: комментарий от dib2

В оффтопике пользовательский интерфейс (в частности, GDI) работает с привилегиями ядра. А в GDI есть прекрасная функция ScaleWindowExtEx, которая делит один целочисленный аргумент на другой.

Но вот интересно: нашли ли аналогичную функцию в ядре Linux? А то bash — как-то мелко.

GolemXIV
()
Ответ на: комментарий от GolemXIV

гденить в сетевом стеке, так что PingOfDeath пока еще может быть актуален 8)

Deleted
()
Ответ на: комментарий от tazhate

А на ppc не падает

# bash
bash-3.2# echo $((-2**63/-1))
-9223372036854775808
bash-3.2# bash --version
GNU bash, version 3.2.16(1)-release (powerpc-ibm-aix5.2.0.0)
Copyright (C) 2005 Free Software Foundation, Inc.
user_undefined
()

Не работает :<

kosyak@knetbook ~ $ echo $((-2**31/-1))
2147483648
kosyak@knetbook ~ $ bash --version
GNU bash, version 4.2.37(1)-release (i686-pc-linux-gnu)

Kosyak ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.