rnpgp / rnp

RNP: high performance C++ OpenPGP library used by Mozilla Thunderbird
https://www.rnpgp.org
Other
201 stars 55 forks source link

`rnp_key_store_clear` throws runtime exception in MSVC #1259

Closed rrrooommmaaa closed 4 years ago

rrrooommmaaa commented 4 years ago

Description

The line keyring->keys.clear(); sometimes triggers runtime exception in MSVC. Perhaps, some iterator is referencing a deleted object (incorrect order of destruction). Does anyone have an idea where we could possibly have made a mess with iterators etc.?

rnp_tests.exe!std::_Iterator_base12::_Orphan_me() Line 1183
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\xmemory(1183)
rnp_tests.exe!std::_Iterator_base12::~_Iterator_base12() Line 1145
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\xmemory(1145)
rnp_tests.exe!std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>,std::_Iterator_base12>::~_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>,std::_Iterator_base12>()
rnp_tests.exe!std::_List_const_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>::~_List_const_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>()
rnp_tests.exe!std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>::~_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>()
rnp_tests.exe!std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>::~pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>()
rnp_tests.exe!std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>::`scalar deleting destructor'(unsigned int)
rnp_tests.exe!std::_Default_allocator_traits<std::allocator<std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>>>::destroy<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>>(std::allocator<std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>> & __formal, std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>> * const _Ptr) Line 677
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\xmemory(677)
rnp_tests.exe!std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>::_Freenode<std::allocator<std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>>>(std::allocator<std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>> & _Al, std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *> * _Ptr) Line 318
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\list(318)
rnp_tests.exe!std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>::_Free_non_head<std::allocator<std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>>>(std::allocator<std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *>> & _Al, std::_List_node<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,void *> * _Head) Line 330
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\list(330)
rnp_tests.exe!std::list<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>,std::allocator<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>>>::clear() Line 1431
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\list(1431)
rnp_tests.exe!std::_Hash<std::_Umap_traits<pgp_fingerprint_t,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>,std::_Uhash_compare<pgp_fingerprint_t,std::hash<pgp_fingerprint_t>,std::equal_to<pgp_fingerprint_t>>,std::allocator<std::pair<pgp_fingerprint_t const ,std::_List_iterator<std::_List_val<std::_List_simple_types<pgp_key_t>>>>>,0>>::clear() Line 1282
    at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include\xhash(1282)
rnp_tests.exe!rnp_key_store_clear(rnp_key_store_t * keyring) Line 227
    at C:\dev\rnp_forks\WINDOWS\rnp\src\librekey\rnp_key_store.cpp(227)
rnp_tests.exe!rnp_key_store_t::~rnp_key_store_t() Line 1027
    at C:\dev\rnp_forks\WINDOWS\rnp\src\librekey\rnp_key_store.cpp(1027)
[External Code]
rnp_tests.exe!rnp_ffi_destroy(rnp_ffi_st * ffi) Line 528
    at C:\dev\rnp_forks\WINDOWS\rnp\src\lib\rnp.cpp(528)

Steps to Reproduce

run test_ffi_key_iter test

rrrooommmaaa commented 4 years ago

image

ni4 commented 4 years ago

Strictly speaking, it is incorrect to call obj = (struct rnp_identifier_iterator_st *) calloc(1, sizeof(*obj)); on rnp_identifier_iterator_st, which has C++ field. (yeah, I know, that's code written by me :) ). Also it is wrong to call free later on it.

While this worked with other compilers, maybe MSVC does things in a bit different way. Maybe changing field keyp type to std::list<pgp_key_t>::iterator * with all the corresponding adjustments may help. Unfortunately I don't have environment with MSVC right now, so cannot check this.