Repository: godotengine/godot (language: cpp)

Issue:
Editor crashes when entering simple if statement
### Tested versions

Master since ba3f4a4b24fe93a77dfd1390f1b0ea4352c664ab

### System information

Godot v4.5.dev (b5bdb8806) - Fedora Linux 41 (Workstation Edition) on Wayland - Wayland display driver, Single-window, 2 monitors - Vulkan (Forward+) - dedicated AMD Radeon RX 6700 XT (RADV NAVI22) - 13th Gen Intel(R) Core(TM) i7-13700K (24 threads)

### Issue description

Since commit ba3f4a4b24fe93a77dfd1390f1b0ea4352c664ab, I am seeing an editor crash if you enter the following text into a script:
```
extends Node3D

var count = 0
func _process(delta):
    if count>0:
```

When pressing enter after the colon, the editor crashes.

Following backtrace is generate:
```
(gdb)  bt
#0  0x0000000003442597 in CowData<char32_t>::get (this=<optimized out>, p_index=<optimized out>) at ./core/templates/cowdata.h:217
#1  String::operator[] (this=<optimized out>, p_index=<optimized out>) at ./core/string/ustring.h:342
#2  GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl (this=0x2c436940, p_line=<optimized out>) at modules/gdscript/editor/gdscript_highlighter.cpp:606
#3  0x00000000060b796b in SyntaxHighlighter::get_line_syntax_highlighting (this=this@entry=0x2c436940, p_line=<optimized out>, p_line@entry=5)
    at scene/resources/syntax_highlighter.cpp:46
#4  0x000000000564681b in TextEdit::_get_line_syntax_highlighting (this=this@entry=0x2c13c7e0, p_line=<optimized out>, p_line@entry=5) at scene/gui/text_edit.cpp:8432
#5  0x0000000005685314 in TextEdit::_notification (this=<optimized out>, p_what=<optimized out>) at scene/gui/text_edit.cpp:883
#6  0x000000000539a5a7 in TextEdit::_notificationv (this=0x2c13c7e0, p_notification=30, p_reversed=false) at ./scene/gui/text_edit.h:41
#7  CodeEdit::_notificationv (this=0x2c13c7e0, p_notification=30, p_reversed=<optimized out>) at scene/gui/code_edit.h:37
#8  0x000000000761c6f8 in Object::notification (this=0x2c13c7e0, p_notification=30, p_reversed=false) at core/object/object.cpp:911
#9  0x00000000051a5d61 in CanvasItem::_redraw_callback (this=0x2c13c7e0) at scene/main/canvas_item.cpp:144
#10 CanvasItem::_redraw_callback (this=0x2c13c7e0) at scene/main/canvas_item.cpp:133
#11 0x00000000076171b8 in CallQueue::_call_function (this=this@entry=0x7de1580, p_callable=..., p_args=p_args@entry=0x995cc58, p_argcount=0, p_show_error=true)
    at core/object/message_queue.cpp:220
#12 0x0000000007617472 in CallQueue::flush (this=0x7de1580) at core/object/message_queue.cpp:268
#13 0x00000000052744ad in SceneTree::physics_process (this=0xa5de390, p_time=0.016666666666666666) at scene/main/scene_tree.cpp:535
#14 0x0000000002b8db72 in Main::iteration () at main/main.cpp:4462
#15 0x0000000002b1b861 in OS_LinuxBSD::run (this=this@entry=0x7fffffffd150) at platform/linuxbsd/os_linuxbsd.cpp:980
#16 0x0000000002b190f5 in main (argc=<optimized out>, argv=0x7fffffffd7a8) at platform/linuxbsd/godot_linuxbsd.cpp:85
```

### Steps to reproduce

1. Create project.
2. Attach script to node.
3. Add an if statement as listed above.

### Minimal reproduction project (MRP)

N/A


Discussion / hints:
I get the following when trying to open one of my projects:
```CrashHandlerException: Program crashed
Engine version: Godot Engine v4.5.dev.custom_build (d768a239bc9529ecee38a2a130fdd3b22e743745)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[0] CowData<String>::get (G:\media\projects\git\godot\core\templates\cowdata.h:218)
[1] Vector<String>::operator[] (G:\media\projects\git\godot\core\templates\vector.h:101)
[2] GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl (G:\media\projects\git\godot\modules\gdscript\editor\gdscript_highlighter.cpp:155)
[3] SyntaxHighlighter::get_line_syntax_highlighting (G:\media\projects\git\godot\scene\resources\syntax_highlighter.cpp:46)
[4] TextEdit::_get_line_syntax_highlighting (G:\media\projects\git\godot\scene\gui\text_edit.cpp:8433)
[5] TextEdit::_notification (G:\media\projects\git\godot\scene\gui\text_edit.cpp:885)
[6] TextEdit::_notificationv (G:\media\projects\git\godot\scene\gui\text_edit.h:41)
[7] CodeEdit::_notificationv (G:\media\projects\git\godot\scene\gui\code_edit.h:37)
[8] Object::notification (G:\media\projects\git\godot\core\object\object.cpp:911)
[9] CanvasItem::_redraw_callback (G:\media\projects\git\godot\scene\main\canvas_item.cpp:145)
[10] call_with_variant_args_helper<CanvasItem> (G:\media\projects\git\godot\core\variant\binder_common.h:314)
[11] call_with_variant_args<CanvasItem> (G:\media\projects\git\godot\core\variant\binder_common.h:428)
[12] CallableCustomMethodPointer<CanvasItem,void>::call (G:\media\projects\git\godot\core\object\callable_method_pointer.h:104)
[13] Callable::callp (G:\media\projects\git\godot\core\variant\callable.cpp:57)
[14] CallQueue::_call_function (G:\media\projects\git\godot\core\object\message_queue.cpp:220)
[15] CallQueue::flush (G:\media\projects\git\godot\core\object\message_queue.cpp:268)
[16] SceneTree::physics_process (G:\media\projects\git\godot\scene\main\scene_tree.cpp:537)
[17] Main::iteration (G:\media\projects\git\godot\main\main.cpp:4462)
[18] ProgressDialog::_update_ui (G:\media\projects\git\godot\editor\progress_dialog.cpp:150)
[19] ProgressDialog::task_step (G:\media\projects\git\godot\editor\progress_dialog.cpp:236)
[20] EditorNode::progress_task_step (G:\media\projects\git\godot\editor\editor_node.cpp:5012)
[21] EditorProgress::step (G:\media\projects\git\godot\editor\editor_node.cpp:182)
[22] EditorNode::_load_editor_layout (G:\media\projects\git\godot\editor\editor_node.cpp:5391)
[23] EditorNode::_sources_changed (G:\media\projects\git\godot\editor\editor_node.cpp:1193)
[24] call_with_variant_args_helper<EditorNode,bool,0> (G:\media\projects\git\godot\core\variant\binder_common.h:314)
[25] call_with_variant_args<EditorNode,bool> (G:\media\projects\git\godot\core\variant\binder_common.h:428)
[26] CallableCustomMethodPointer<EditorNode,void,bool>::call (G:\media\projects\git\godot\core\object\callable_method_pointer.h:104)
[27] Callable::callp (G:\media\projects\git\godot\core\variant\callable.cpp:57)
[28] Object::emit_signalp (G:\media\projects\git\godot\core\object\object.cpp:1237)
[29] Node::emit_signalp (G:\media\projects\git\godot\scene\main\node.cpp:4007)
[30] Object::emit_signal<bool> (G:\media\projects\git\godot\core\object\object.h:932)
[31] EditorFileSystem::_notification (G:\media\projects\git\godot\editor\editor_file_system.cpp:1771)
[32] EditorFileSystem::_notificationv (G:\media\projects\git\godot\editor\editor_file_system.h:148)
[33] Object::notification (G:\media\projects\git\godot\core\object\object.cpp:911)
[34] SceneTree::_process_group (G:\media\projects\git\godot\scene\main\scene_tree.cpp:1066)
[35] SceneTree::_process (G:\media\projects\git\godot\scene\main\scene_tree.cpp:1143)
[36] SceneTree::process (G:\media\projects\git\godot\scene\main\scene_tree.cpp:586)
[37] Main::iteration (G:\media\projects\git\godot\main\main.cpp:4506)
[38] OS_Windows::run (G:\media\projects\git\godot\platform\windows\os_windows.cpp:2075)
[39] widechar_main (G:\media\projects\git\godot\platform\windows\godot_windows.cpp:96)
[40] _main (G:\media\projects\git\godot\platform\windows\godot_windows.cpp:122)
[41] main (G:\media\projects\git\godot\platform\windows\godot_windows.cpp:136)
[42] WinMain (G:\media\projects\git\godot\platform\windows\godot_windows.cpp:150)
[43] __scrt_common_main_seh (D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[44] <couldn't map PC to fn name>
-- END OF BACKTRACE --```
Could one of you provide an MRP for a project that crashes on open? I'm not having any luck reproducing this myself, either on ba3f4a4 or the latest commit to master.
[mrp-crash.zip](https://github.com/user-attachments/files/19144623/mrp-crash.zip)
Thanks! That causes the crash for me, I'll try to get a fix asap.

Fix patch:
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index f36103c34b44..80bf1daf0cd1 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -1175,7 +1175,7 @@ String String::get_slicec(char32_t p_splitter, int p_slice) const {
 	}
 }
 
-Vector<String> String::split_spaces() const {
+Vector<String> String::split_spaces(int p_maxsplit) const {
 	Vector<String> ret;
 	int from = 0;
 	int i = 0;
@@ -1199,6 +1199,11 @@ Vector<String> String::split_spaces() const {
 		}
 
 		if (empty && inside) {
+			if (p_maxsplit > 0 && p_maxsplit == ret.size()) {
+				// Put rest of the string and leave cycle.
+				ret.push_back(substr(from));
+				break;
+			}
 			ret.push_back(substr(from, i - from));
 			inside = false;
 		}
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 46c8fb85e254..c728e8f51352 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -486,7 +486,7 @@ class String {
 	Vector<String> split(const char *p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
 	Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
 	Vector<String> rsplit(const char *p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
-	Vector<String> split_spaces() const;
+	Vector<String> split_spaces(int p_maxsplit = 0) const;
 	Vector<double> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
 	Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
 	Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 4309639fd41a..13902b981df0 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -151,10 +151,13 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
 							}
 						}
 						// "#region" and "#endregion" only highlighted if they're the first region on the line.
-						if (color_regions[c].type == ColorRegion::TYPE_CODE_REGION &&
-								str.strip_edges().split_spaces()[0] != "#region" &&
-								str.strip_edges().split_spaces()[0] != "#endregion") {
-							match = false;
+						if (color_regions[c].type == ColorRegion::TYPE_CODE_REGION) {
+							Vector<String> str_stripped_split = str.strip_edges().split_spaces(1);
+							if (!str_stripped_split.is_empty() &&
+									str_stripped_split[0] != "#region" &&
+									str_stripped_split[0] != "#endregion") {
+								match = false;
+							}
 						}
 						if (!match) {
 							continue;
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index a78408b9ab9f..c1d726f4e312 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -1872,7 +1872,7 @@ bool CodeEdit::is_line_code_region_start(int p_line) const {
 	if (is_in_string(p_line) != -1) {
 		return false;
 	}
-	Vector<String> split = get_line(p_line).strip_edges().split_spaces();
+	Vector<String> split = get_line(p_line).strip_edges().split_spaces(1);
 	return split.size() > 0 && split[0] == code_region_start_string;
 }
 
@@ -1884,7 +1884,7 @@ bool CodeEdit::is_line_code_region_end(int p_line) const {
 	if (is_in_string(p_line) != -1) {
 		return false;
 	}
-	Vector<String> split = get_line(p_line).strip_edges().split_spaces();
+	Vector<String> split = get_line(p_line).strip_edges().split_spaces(1);
 	return split.size() > 0 && split[0] == code_region_end_string;
 }
 


Test patch:
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 35f693a3ceed..16fde32307c8 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -713,6 +713,14 @@ TEST_CASE("[String] Splitting") {
 			CHECK(l[i] == slices[i]);
 		}
 	}
+	{
+		const String s = "Mars Jupiter Saturn Uranus";
+		const char *slices[2] = { "Mars", "Jupiter Saturn Uranus" };
+		Vector<String> l = s.split_spaces(1);
+		for (int i = 0; i < l.size(); i++) {
+			CHECK(l[i] == slices[i]);
+		}
+	}
 
 	{
 		const String s = "1.2;2.3 4.5";