2016-07-15 1 views
6

У меня есть шаблон функции со специализацией, которая выполняет zeroization:Как тренировать Coverity для обнаружения «подозрительного размера» или SIZEOF_MISMATCH?

template <class T> 
void SecureWipeBuffer(T *buf, size_t n) 
{ 
    volatile T *p = buf+n; 
    while (n--) 
     *((volatile T*)(--p)) = 0; 
} 
... 

template <> 
void SecureWipeBuffer(word64* p, size_t n) 
{ 
    asm volatile("rep stosq" : "+c"(n), "+D"(p) : "a"(0) : "memory"); 
} 

Coverity производит вывод о SecureWipeBuffer:

word64 val; 
... 
SecureWipeBuffer(&val, 1); 

Находить является:

>>>  CID 164713: Incorrect expression (SIZEOF_MISMATCH) 
>>>  Passing argument "&val" of type "word64 *" and argument "1UL" to function "SecureWipeBuffer" is suspicious because "sizeof (word64)" /*8*/ is expected. 
275    SecureWipeBuffer(&val, 1); 

Как сделать поезд Покрытие, которое SecureWipeBuffer принимает количество элементов, а не количество байтов?


EDIT: мы подобрали два подобных результатов с нашим кодом Windows. Кроме того, Coverity производит выводы о стандартных библиотечных функциях. Как будто он не понимает, что C++ имеет дело с количеством элементов, а не количеством байтов.

Ниже от Microsft стандартного кода библиотеки в <xmemory>

25 if (_Count == 0) 
26  ; 
27 else if (((size_t)(-1)/sizeof (_Ty) < _Count) 
    CID 12348 (#1 of 1): Wrong sizeof argument (SIZEOF_MISMATCH) 
    suspicious_sizeof: Passing argument _Count * 4U /* sizeof (std::allocator<void *>::value_type) */ 
    to function operator new which returns a value of type std::allocator<void *>::value_type is suspicious. 
28  || (_Ptr = ::operator new(_Count * sizeof (_Ty))) == 0) 
29   _Xbad_alloc(); // report no memory 
+1

'-p' уже имеет тип' volatile T * ', поэтому литье является избыточным –

+1

В случае, если вы не знаете, в неспециализированной версии стандарт позволяет оптимизировать' volatile' и компилятор может даже заменить это вызовом memset. (правило о сохранении доступа к энергозависимым объектам - это просто, а не доступ с помощью неактивных указателей). –

+1

@ M.M - * "' --p' уже имеет тип 'volatile T *', поэтому литье является избыточным * * - вы думаете, что, но две версии GCC не могут делать то, что ожидается. Составители, делающие неожиданные вещи, являются причиной того, что мы должны запустить этот цикл в обратном порядке. Его одна из радостей поддержки 20 лет компиляторов практически на каждой крупной платформе. – jww

ответ

2

Я нашел Github, который пытается подавить, что *, делая это:

std::fill_n(out, spec_.width_ - 1, fill); 
    out += spec_.width_ - 1; 
} else if (spec_.align_ == ALIGN_CENTER) { 
    // coverity[suspicious_sizeof] 
    out = writer_.fill_padding(out, spec_.width_, 1, fill); 
} else { 
    std::fill_n(out + 1, spec_.width_ - 1, fill); 

который также рекомендуется в Silencing false positives in Coverity Prevent, и здесь рассматривается другой подход: Coverity SA - excluding boost, stlport errors.


* Я не уверен, если это то, что вы хотите, но это все, что я получил!

+2

Спасибо gsamaras.Я обдумал это в течение нескольких недель (я был на пятом месте назад). Это похоже на хак, и я думаю, что проблема должна быть решена каким-то другим способом. Я поставил щедрость на этот вопрос в надежде привлечь кого-то из заинтересованных лиц. Надеюсь, один из ребят Coverity объяснит, почему анализ обрабатывает количество элементов C++ как «количество байтов»; и, надеюсь, они расскажут нам, как обращаться с ним без взлома (кодовые аннотации, моделирование и т. д.). – jww

+1

Отличный @jww, мне любопытно! :) – gsamaras