Clang Sanitizer неправильно ловит целочисленное переполнение - PullRequest
3 голосов
/ 16 января 2020

Скажите, что мой size_type равен uint64_t, и у меня есть следующее l oop (где sz тоже size_type)

for ( size_type i= 0; i < sz; ++i ) {
     //something
     if ( i+1 == sz ) { //<-- here
         ///
     }
}

Теперь при компиляции с флагами -fno-omit-frame-pointer -fsanitize=undefined -O2 -fsanitize=address, я получаю ошибку времени выполнения, которая говорит, что в месте, которое я пометил here в фрагменте кода выше, 2147483647 + 1 cannot fit into integer, и это правда, что sz немного больше, чем 2^31-1. Однако все должно быть в порядке, потому что uint64_t может содержать значение, а по правилам преобразования i+1 должно быть переведено в uint64_t. Что мне не хватает? РЕДАКТИРОВАТЬ: Разве это не так, что uint64_t всегда имеет 64 бит? Тогда 2147... -значение просто 32 бит, и мы все равно должны быть в порядке. Теперь я использую свою вещь без дезинфицирующих средств, и до сих пор не произошло никакого сумасшествия sh. РЕДАКТИРОВАТЬ:

clang версия 8.0.0-3 ~ ubuntu18.04.1 (tags / RELEASE_800 / final) Цель: x86_64-p c - linux -gnu Модель потока: posix

, а также у меня есть следующие флаги компоновщика

set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address")

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

1 Ответ

0 голосов
/ 18 января 2020

Во время последней итерации i = UINT64_MAX - 1, поэтому i+1 = UINT64_MAX, поэтому i <= UINT64_MAX во всех случаях.

for ( size_type i= 0; i < sz; ++i ) {
     //something
     if ( i+1 == sz ) { //<-- here
         ///
     }
}

Нет переполнения. Существует вероятность ошибки в clang, когда он пытается выполнить некорректную оптимизацию индукционной переменной.

clang-8, rcx увеличивается до тех пор, пока не достигнет 0. Это может привести к отключению на 1 error .

.LBB1_4:
        neg     rcx 
.LBB1_5:                                # =>This Inner Loop Header: Depth=1
        cmp     rax, rdi 
        jne     .LBB1_7
        mov     qword ptr [rsp - 8], rdi 
.LBB1_7:                                #   in Loop: Header=BB1_5 Depth=1
        add     rdi, 1
        inc     rcx 
        jne     .LBB1_5
.LBB1_8:

во время лязга-9. rcx уменьшается до тех пор, пока не достигнет 0.

.LBB1_7:
        ret 
.LBB1_6:                                #   in Loop: Header=BB1_4 Depth=1
        add     rdi, 1
        add     rcx, -1
        je      .LBB1_7
.LBB1_4:                                # =>This Inner Loop Header: Depth=1
        cmp     rax, rdi 
        jne     .LBB1_6
        mov     qword ptr [rsp - 8], rdi 
        jmp     .LBB1_6
...