Repository: godotengine/godot (language: cpp)

Issue:
CI `Test Godot project` on Linux doesn't run at all
### Tested versions

4.5

### System information

N/A

### Issue description

When I test https://github.com/godotengine/regression-test-project/tree/4.0, Godot crashed. After I checked the CI I found the regression test project didn't run at all. For example, see the log in https://github.com/godotengine/godot/actions/runs/14071078496/job/39405241293
```
UndefinedBehaviorSanitizer: failed to read suppressions file '/home/runner/work/godot/godot/bin/misc/error_suppressions/ubsan.txt'
...
UndefinedBehaviorSanitizer: failed to read suppressions file '/home/runner/work/godot/godot/bin/misc/error_suppressions/ubsan.txt'

```
Not sure when this issue began to happen.

### Steps to reproduce

See CI `Test Godot Project` in `🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)`

### Minimal reproduction project (MRP)

N/A


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 5a0dea07d3f8..6305db26e2c1 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -8,8 +8,8 @@ env:
   SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes
   DOTNET_NOLOGO: true
   DOTNET_CLI_TELEMETRY_OPTOUT: true
-  TSAN_OPTIONS: suppressions=misc/error_suppressions/tsan.txt
-  UBSAN_OPTIONS: suppressions=misc/error_suppressions/ubsan.txt
+  TSAN_OPTIONS: suppressions=${{ github.workspace }}/misc/error_suppressions/tsan.txt
+  UBSAN_OPTIONS: suppressions=${{ github.workspace }}/misc/error_suppressions/ubsan.txt
 
 jobs:
   build-linux:
diff --git a/scene/3d/spring_bone_simulator_3d.cpp b/scene/3d/spring_bone_simulator_3d.cpp
index 91b3906edf77..54ae2807f32b 100644
--- a/scene/3d/spring_bone_simulator_3d.cpp
+++ b/scene/3d/spring_bone_simulator_3d.cpp
@@ -607,6 +607,7 @@ void SpringBoneSimulator3D::set_radius(int p_index, float p_radius) {
 }
 
 float SpringBoneSimulator3D::get_radius(int p_index) const {
+	ERR_FAIL_INDEX_V(p_index, settings.size(), 0);
 	return settings[p_index]->radius;
 }
 
@@ -640,6 +641,7 @@ void SpringBoneSimulator3D::set_stiffness(int p_index, float p_stiffness) {
 }
 
 float SpringBoneSimulator3D::get_stiffness(int p_index) const {
+	ERR_FAIL_INDEX_V(p_index, settings.size(), 0);
 	return settings[p_index]->stiffness;
 }
 
@@ -762,8 +764,15 @@ SpringBoneSimulator3D::RotationAxis SpringBoneSimulator3D::get_rotation_axis(int
 
 void SpringBoneSimulator3D::set_setting_count(int p_count) {
 	ERR_FAIL_COND(p_count < 0);
-	int delta = p_count - settings.size() + 1;
+
+	int delta = p_count - settings.size();
+	if (delta < 0) {
+		for (int i = delta; i < 0; i++) {
+			memdelete(settings[settings.size() + i]);
+		}
+	}
 	settings.resize(p_count);
+	delta++;
 	if (delta > 1) {
 		for (int i = 1; i < delta; i++) {
 			settings.write[p_count - i] = memnew(SpringBone3DSetting);
@@ -949,8 +958,14 @@ void SpringBoneSimulator3D::set_joint_count(int p_index, int p_count) {
 	ERR_FAIL_INDEX(p_index, settings.size());
 	ERR_FAIL_COND(p_count < 0);
 	Vector<SpringBone3DJointSetting *> &joints = settings[p_index]->joints;
-	int delta = p_count - joints.size() + 1;
+	int delta = p_count - joints.size();
+	if (delta < 0) {
+		for (int i = delta; i < 0; i++) {
+			memdelete(joints[joints.size() + i]);
+		}
+	}
 	joints.resize(p_count);
+	delta++;
 	if (delta > 1) {
 		for (int i = 1; i < delta; i++) {
 			joints.write[p_count - i] = memnew(SpringBone3DJointSetting);
@@ -1659,3 +1674,7 @@ Quaternion SpringBoneSimulator3D::get_from_to_rotation(const Vector3 &p_from, co
 	}
 	return Quaternion(axis.normalized(), angle);
 }
+
+SpringBoneSimulator3D::~SpringBoneSimulator3D() {
+	clear_settings();
+}
diff --git a/scene/3d/spring_bone_simulator_3d.h b/scene/3d/spring_bone_simulator_3d.h
index 7f0583bb629b..e01ab1deee75 100644
--- a/scene/3d/spring_bone_simulator_3d.h
+++ b/scene/3d/spring_bone_simulator_3d.h
@@ -284,6 +284,8 @@ class SpringBoneSimulator3D : public SkeletonModifier3D {
 #ifdef TOOLS_ENABLED
 	virtual bool is_processed_on_saving() const override { return true; }
 #endif
+
+	~SpringBoneSimulator3D();
 };
 
 VARIANT_ENUM_CAST(SpringBoneSimulator3D::BoneDirection);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 8b0fe63f5a18..92b92dd8bb4a 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -2330,6 +2330,8 @@ TypedArray<Dictionary> GraphEdit::_get_connections_intersecting_with_rect(const
 }
 
 TypedArray<Dictionary> GraphEdit::_get_connection_list_from_node(const StringName &p_node) const {
+	ERR_FAIL_COND_V(!connection_map.has(p_node), TypedArray<Dictionary>());
+
 	List<Ref<GraphEdit::Connection>> connections_from_node = connection_map.get(p_node);
 	TypedArray<Dictionary> connections_from_node_dict;
 


Test patch: