-
Notifications
You must be signed in to change notification settings - Fork 51
OpenSSF silver badge: fix the issues on hardening #1264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/hardening
Are you sure you want to change the base?
Conversation
Signed-off-by: Martijn Govers <Martijn.Govers@Alliander.com>
|
|
What undefined behavior we are talking about? What we do is a well-known practice for many libraries, to declare an opaque type in C-API user side. But in C-API implementation side, we surpress that opaque type, and instead directly have a using directive to refer to a concrete type inside namespace. |
|
Hi @mgovers, after some digging I see this is indeed UB. Not because of pointer case, which is well-defined if you do round-trip opaque pointer cast and never dereference the opaque pointer (you can't anyway). But because the function signature has different types between translation units. But I do not think using wrapper type (even for So I would propose to just pre-define a template<class c_type, class cpp_type>
struct type_matching;
template<class...>
struct type_matching_list_impl;
using type_matching_list = typematching_list<
type_matching<PGM_MetaComponent, power_grid_model::meta_data::MetaComponent>,
// list all opaque to concrete type matching
>;
template<class c_type_pointer>
using cpp_type_pointer_t = // some template magic to find the correct cpp type pointer, also keep const correctness
template<class c_type_pointer>
auto cast_to_cpp(c_type_pointer ptr) {
return reintepret_cast<cpp_type_pointer_t<c_type_pointer>>(ptr);
}
template<class cpp_type_pointer>
using c_type_pointer_t = // some template magic to find the correct c type pointer, also keep const correctness
template<class cpp_type_pointer>
auto cast_to_c(cpp_type_pointer ptr) {
return reintepret_cast<c_type_pointer_t<cpp_type_pointer>>(ptr);
}After this, we can
|
I thought about something along those lines as well, but then we still have the |
That's not needed. We do not need to define a forward opaque type. We can just cast between |
let me try |



in #1241, hardening was enabled. Clang actually raised some valid undefined behavior issues:
The underlying reason was that we do
and the C API implementation then contains
but the user will import like
This effectively means that the C API implementation will see a type
while the user will see a type
Or, in short, the user will see a type
struct PGM_ConstDatasetthat is its own type, but the implementation will see the typepower_grid_model::meta_data::ConstDatast.After digging into it, it seemed very similar to something that was found in the CPython implementation (python/cpython#111178). I then found that we do not have such issues for
PGM_PowerGridModel, the implementation of which is defined asstruct PGM_PowerGridModel: public power_grid_model::MainModel {};, which IS, in fact, its own type, rather than a type alias that comes from ausingdeclaration.The reason a
usingdeclaration was used in the first place is so that we could apply forward declarations, but now it seems that this was not the right solution. Note as well that the#ifndef PGM_DLL_EXPORTguard was used in the first place to suppress the exact same compiler errors, but we did not realize that the same undefined behavior was still being invoked on the user side.To solve the issue in a way that still allows support for both features, I ended up following a similar approach as to main model, by using a derived type implementation, but also added forward declared, statically linked
wrapandunwrapfunctions to handle the type conversions for files that use the forward declared version.