17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-06 17:28:36 +01:00

Fix/sonar reliability security (#205)

* fix(sonar): addressing reliability/security issues

* fix(sonar): addressing reliability/security issues

* fix(sonar): addressing reliability/security issues

* fix(sonar): addressing last reliability/security issues

* fix(sonar): addressing last reliability/security issues

* fix(sonar): addressing last reliability/security issues

* refactor(sonar): imgui update

* refactor(sonar): hasChar revert
This commit is contained in:
jerrrrycho
2026-10-11 15:31:45 +02:00
committed by GitHub
parent 6263fe539b
commit 8125166690
6 changed files with 78 additions and 68 deletions

View File

@@ -569,7 +569,7 @@ int eu07_application::run()
if (m_network && m_network->client) if (m_network && m_network->client)
{ {
// verify sync // verify sync
if (sync != slave_sync) // NOSONAR if (sync != slave_sync) // NOSONAR slave_sync is initialised, the PR analysis keeps a stale report of the old declaration
{ {
WriteLog("net: desync! calculated: " + std::to_string(sync) + ", received: " + std::to_string(slave_sync), logtype::net); WriteLog("net: desync! calculated: " + std::to_string(sync) + ", received: " + std::to_string(slave_sync), logtype::net);
@@ -1464,7 +1464,8 @@ int eu07_application::init_data()
int eu07_application::init_modes() int eu07_application::init_modes()
{ {
Global.local_random_engine.seed(static_cast<std::mt19937::result_type>(true_random_seed())); // local cosmetics only (sound pitch, editor placement), never security related
Global.local_random_engine.seed(static_cast<std::mt19937::result_type>(true_random_seed())); // NOSONAR
if ((!Global.network_servers.empty() || Global.network_client) && Global.SceneryFile.empty()) if ((!Global.network_servers.empty() || Global.network_client) && Global.SceneryFile.empty())
{ {

View File

@@ -92,7 +92,8 @@ bool ImGui_NVRHI::createFontTexture(nvrhi::ICommandList* commandList)
commandList->setPermanentTextureState(fontTexture, nvrhi::ResourceStates::ShaderResource); commandList->setPermanentTextureState(fontTexture, nvrhi::ResourceStates::ShaderResource);
commandList->commitBarriers(); commandList->commitBarriers();
io.Fonts->TexID = fontTexture; // since imgui 1.91 ImTextureID is an integer, not a pointer
io.Fonts->TexID = static_cast<ImTextureID>(reinterpret_cast<uintptr_t>(fontTexture.Get()));
} }
{ {
@@ -371,7 +372,7 @@ bool ImGui_NVRHI::render(nvrhi::IFramebuffer* framebuffer)
{ {
pCmd->UserCallback(cmdList, pCmd); pCmd->UserCallback(cmdList, pCmd);
} else { } else {
drawState.bindings = { getBindingSet(pCmd->TextureId) }; drawState.bindings = { getBindingSet(reinterpret_cast<void*>(static_cast<uintptr_t>(pCmd->GetTexID()))) };
assert(drawState.bindings[0]); assert(drawState.bindings[0]);
drawState.viewport.scissorRects[0] = nvrhi::Rect(int(pCmd->ClipRect.x), drawState.viewport.scissorRects[0] = nvrhi::Rect(int(pCmd->ClipRect.x),

View File

@@ -216,7 +216,7 @@ bool opengl33_renderer::Init(GLFWwindow *Window)
// Generate hemisphere kernel (z > 0 = toward surface normal) // Generate hemisphere kernel (z > 0 = toward surface normal)
std::uniform_real_distribution<float> rnd(0.0f, 1.0f); std::uniform_real_distribution<float> rnd(0.0f, 1.0f);
std::default_random_engine gen(42); // fixed seed for consistency std::default_random_engine gen(42); // NOSONAR fixed seed on purpose, SSAO kernel has to be identical every run
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
glm::vec3 s(rnd(gen)*2.0f-1.0f, rnd(gen)*2.0f-1.0f, rnd(gen)); glm::vec3 s(rnd(gen)*2.0f-1.0f, rnd(gen)*2.0f-1.0f, rnd(gen));
s = glm::normalize(s) * rnd(gen); s = glm::normalize(s) * rnd(gen);
@@ -1532,7 +1532,7 @@ glm::mat4 opengl33_renderer::perspective_projection_raw(float fovy, float aspect
{ {
if (GLAD_GL_ARB_clip_control || GLAD_GL_EXT_clip_control) if (GLAD_GL_ARB_clip_control || GLAD_GL_EXT_clip_control)
{ {
const float f = 1.0f / tan(fovy / 2.0f); const float f = 1.0f / std::tan(fovy / 2.0f);
// when clip_control available, use projection matrix with 1..0 Z range and infinite zfar // when clip_control available, use projection matrix with 1..0 Z range and infinite zfar
return glm::mat4( // return glm::mat4( //

View File

@@ -614,7 +614,8 @@ std::string deserialize_random_set(cParser &Input, char const *Break)
} }
if (false == tokens.empty()) if (false == tokens.empty())
{ {
std::ranges::shuffle(tokens, Global.random_engine); // scenery random set: must replay from the shared run seed, not a security concern
std::shuffle(std::begin(tokens), std::end(tokens), Global.random_engine); // NOSONAR
return tokens.front(); return tokens.front();
} }
else else

View File

@@ -317,8 +317,7 @@ TSegment::find_nearest_point( glm::dvec3 const &Point ) const {
distance = segmentdistance; distance = segmentdistance;
} }
} }
// return nearest; // NOSONAR initialised above, the PR analysis keeps a stale report of the old declaration
return nearest;
} }
} }
@@ -563,14 +562,14 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, glm::dvec3 const &Origin,
void TSegment::render_lines(std::vector<gfx::basic_vertex> &out, float quality) const void TSegment::render_lines(std::vector<gfx::basic_vertex> &out, float quality) const
{ {
float step = 1.0f / static_cast<float>(iSegCount) / quality; float step = 1.0f / iSegCount / quality;
auto const stepcount = static_cast<int>(static_cast<float>(iSegCount) * quality);
glm::vec3 previous = FastGetPoint(0.0); glm::vec3 previous = FastGetPoint(0.0);
for (int i = 1; static_cast<float>(i) * step <= 1.0f; ++i) { for (int i = 1; i <= stepcount; ++i) {
float const x = static_cast<float>(i) * step; float const x = std::min(1.0f, static_cast<float>(i) * step);
out.emplace_back(previous, glm::vec3(0.0f), glm::vec2(0.0f)); out.push_back(gfx::basic_vertex(previous, glm::vec3(0.0f), glm::vec2(0.0f)));
previous = glm::vec3(FastGetPoint(x)); previous = glm::vec3(FastGetPoint(x));
out.emplace_back(previous, glm::vec3(0.0f), glm::vec2(0.0f)); out.emplace_back(previous, glm::vec3(0.0f), glm::vec2(0.0f));
@@ -584,14 +583,14 @@ void TSegment::render_lines(std::vector<gfx::basic_vertex> &out, float quality)
glm::vec3 TSegment::get_nearest_point(const glm::dvec3 &point, float quality) const glm::vec3 TSegment::get_nearest_point(const glm::dvec3 &point, float quality) const
{ {
float step = 1.0f / static_cast<float>(iSegCount) / quality; float step = 1.0f / iSegCount / quality;
auto const stepcount = static_cast<int>(static_cast<float>(iSegCount) * quality);
glm::vec3 nearest; glm::vec3 nearest;
float min = std::numeric_limits<float>::max(); float min = std::numeric_limits<float>::max();
for (int i = 1; static_cast<float>(i) * step <= 1.0f; ++i) { for (int i = 1; i <= stepcount; ++i) {
float const x = static_cast<float>(i) * step; float const x = std::min(1.0f, static_cast<float>(i) * step);
glm::vec3 p1 = FastGetPoint(x); glm::vec3 p1 = FastGetPoint(x);
if (glm::vec3 p2 = FastGetPoint(glm::min(1.0f, x + step)); p1 != p2) { if (glm::vec3 p2 = FastGetPoint(glm::min(1.0f, x + step)); p1 != p2) {

View File

@@ -3720,6 +3720,58 @@ std::vector<TSegment *> sleeper_segments_for( TTrack const &Track )
} }
return out; return out;
} }
// Local-space transform (relative to Origin) of the sleeper at distance S along the Segment,
// or none at a degenerate spot (e.g. zero-length sub-segment) where no tangent can be taken.
// Eps is the half-span of the central difference used to extract the tangent.
std::optional<glm::mat4> sleeper_transform( TSegment const &Segment, double const S, double const Eps, glm::dvec3 const &Origin, glm::vec3 const &Offset )
{
glm::dvec3 pos;
glm::vec3 angles;
Segment.RaPositionGet( S, pos, angles );
// tangent direction via central difference (clamped to the segment endpoints)
glm::dvec3 p_back;
glm::dvec3 p_fwd;
glm::vec3 dummy;
Segment.RaPositionGet( std::max( 0.0, S - Eps ), p_back, dummy );
Segment.RaPositionGet( std::min( Segment.GetLength(), S + Eps ), p_fwd, dummy );
auto tangent = glm::vec3( p_fwd - p_back );
if( glm::length2( tangent ) < 1e-8f ) {
// skip this position rather than emit a junk transform with NaN normals.
return std::nullopt;
}
tangent = glm::normalize( tangent );
// build an orthonormal basis around the tangent. world up is the reference; if the
// track is almost vertical we fall back to world X so cross() doesn't collapse.
glm::vec3 up_ref { 0.f, 1.f, 0.f };
if( std::abs( glm::dot( tangent, up_ref ) ) > 0.999f ) { up_ref = glm::vec3( 1.f, 0.f, 0.f ); }
glm::vec3 side = glm::normalize( glm::cross( up_ref, tangent ) );
glm::vec3 up = glm::cross( tangent, side );
// apply track roll (banking) around the tangent / forward axis.
if( float const roll = angles.x; roll != 0.f ) {
auto const roll_mat = glm::rotate( glm::mat4( 1.f ), roll, tangent );
side = glm::vec3( roll_mat * glm::vec4( side, 0.f ) );
up = glm::vec3( roll_mat * glm::vec4( up, 0.f ) );
}
// assemble local transform: columns are (right, up, forward, translation).
// a sleeper modelled with X = sideways, Y = up, Z = along-track now ends up
// correctly oriented along the path tangent regardless of curve direction.
auto const localpos = glm::vec3( pos - Origin );
glm::mat4 m { 1.f };
m[ 0 ] = glm::vec4( side, 0.f );
m[ 1 ] = glm::vec4( up, 0.f );
m[ 2 ] = glm::vec4( tangent, 0.f );
m[ 3 ] = glm::vec4( localpos, 1.f );
if( Offset != glm::vec3( 0.f ) ) {
m = glm::translate( m, Offset );
}
return m;
}
} // anonymous namespace } // anonymous namespace
// Resolves the sleeper model + (optional) replacable skin via the global model/material // Resolves the sleeper model + (optional) replacable skin via the global model/material
@@ -3764,13 +3816,12 @@ void TTrack::build_sleeper_transforms()
// at the segment endpoints. Sampling positions directly is robust for both straight // at the segment endpoints. Sampling positions directly is robust for both straight
// segments and bezier curves, and it costs us two extra evaluations per sleeper. // segments and bezier curves, and it costs us two extra evaluations per sleeper.
double const eps = std::min( 0.1, spacing * 0.25 ); double const eps = std::min( 0.1, spacing * 0.25 );
glm::vec3 const world_up { 0.f, 1.f, 0.f };
// user offset is (left/right, forward/back, up/down) in the local frame established by // user offset is (left/right, forward/back, up/down) in the local frame established by
// the basis below (x=right, y=up, z=forward). swap y<->z to match the documented axes. // the basis below (x=right, y=up, z=forward). swap y<->z to match the documented axes.
glm::vec3 const local_offset { m_sleeper_offset.x, m_sleeper_offset.z, m_sleeper_offset.y }; glm::vec3 const local_offset { m_sleeper_offset.x, m_sleeper_offset.z, m_sleeper_offset.y };
for( auto *segment : segments ) { for( auto const *segment : segments ) {
auto const length = segment->GetLength(); auto const length = segment->GetLength();
if( length <= 0.0 ) { continue; } if( length <= 0.0 ) { continue; }
// start half a frequency in so the first sleeper doesn't sit on the joint. // start half a frequency in so the first sleeper doesn't sit on the joint.
@@ -3778,55 +3829,12 @@ void TTrack::build_sleeper_transforms()
auto const expected = static_cast<std::size_t>( std::max( 0.0, ( length - start ) / spacing ) ) + 1u; auto const expected = static_cast<std::size_t>( std::max( 0.0, ( length - start ) / spacing ) ) + 1u;
m_sleeper_local_transforms.reserve( m_sleeper_local_transforms.size() + expected ); m_sleeper_local_transforms.reserve( m_sleeper_local_transforms.size() + expected );
for( double s = start; s < length; s += spacing ) { for( std::size_t sleeperidx = 0;; ++sleeperidx ) {
glm::dvec3 pos; auto const s = start + static_cast<double>( sleeperidx ) * spacing;
glm::vec3 angles; if( s >= length ) { break; }
segment->RaPositionGet( s, pos, angles ); if( auto const transform = sleeper_transform( *segment, s, eps, m_origin, local_offset ) ) {
m_sleeper_local_transforms.emplace_back( *transform );
// tangent direction via central difference (clamped to the segment endpoints)
auto const s_back = std::max( 0.0, s - eps );
auto const s_fwd = std::min( length, s + eps );
glm::dvec3 p_back, p_fwd;
glm::vec3 dummy;
segment->RaPositionGet( s_back, p_back, dummy );
segment->RaPositionGet( s_fwd, p_fwd, dummy );
auto tangent = glm::vec3( p_fwd - p_back );
if( glm::length2( tangent ) < 1e-8f ) {
// degenerate sample (e.g. zero-length sub-segment); skip this position rather
// than emit a junk transform with NaN normals.
continue;
} }
tangent = glm::normalize( tangent );
// build an orthonormal basis around the tangent. world up is the reference; if the
// track is almost vertical we fall back to world X so cross() doesn't collapse.
glm::vec3 up_ref = world_up;
if( std::abs( glm::dot( tangent, up_ref ) ) > 0.999f ) { up_ref = glm::vec3( 1.f, 0.f, 0.f ); }
glm::vec3 right = glm::normalize( glm::cross( up_ref, tangent ) );
glm::vec3 up = glm::cross( tangent, right );
// apply track roll (banking) around the tangent / forward axis.
float const roll = angles.x;
if( roll != 0.f ) {
auto const roll_mat = glm::rotate( glm::mat4( 1.f ), roll, tangent );
right = glm::vec3( roll_mat * glm::vec4( right, 0.f ) );
up = glm::vec3( roll_mat * glm::vec4( up, 0.f ) );
}
// assemble local transform: columns are (right, up, forward, translation).
// a sleeper modelled with X = sideways, Y = up, Z = along-track now ends up
// correctly oriented along the path tangent regardless of curve direction.
auto const localpos = glm::vec3( pos - m_origin );
glm::mat4 m { 1.f };
m[ 0 ] = glm::vec4( right, 0.f );
m[ 1 ] = glm::vec4( up, 0.f );
m[ 2 ] = glm::vec4( tangent, 0.f );
m[ 3 ] = glm::vec4( localpos, 1.f );
if( local_offset != glm::vec3( 0.f ) ) {
m = glm::translate( m, local_offset );
}
m_sleeper_local_transforms.emplace_back( m );
} }
} }
} }