Browse Source

Merge pull request #46992 from akien-mga/3.2-cherrypicks

Cherry-picks for the 3.2 branch (future 3.2.4) - 29th batch
Rémi Verschelde 4 years ago
parent
commit
6a9e7c5a53
53 changed files with 552 additions and 173 deletions
  1. 7 4
      SConstruct
  2. 4 3
      core/io/file_access_compressed.cpp
  3. 4 2
      core/io/file_access_encrypted.cpp
  4. 2 1
      core/io/file_access_memory.cpp
  5. 2 0
      core/io/file_access_network.cpp
  6. 2 0
      core/io/file_access_pack.cpp
  7. 2 1
      core/io/file_access_zip.cpp
  8. 2 1
      core/os/file_access.cpp
  9. 18 12
      drivers/coreaudio/audio_driver_coreaudio.cpp
  10. 2 1
      drivers/unix/file_access_unix.cpp
  11. 2 1
      drivers/windows/file_access_windows.cpp
  12. 2 2
      editor/editor_file_dialog.cpp
  13. 8 5
      editor/editor_node.cpp
  14. 1 1
      editor/editor_properties.cpp
  15. 6 2
      editor/editor_spin_slider.cpp
  16. 2 2
      editor/plugins/abstract_polygon_2d_editor.cpp
  17. 19 12
      editor/plugins/asset_library_editor_plugin.cpp
  18. 1 0
      editor/plugins/asset_library_editor_plugin.h
  19. 3 4
      editor/plugins/spatial_editor_plugin.cpp
  20. 2 2
      editor/scene_tree_editor.cpp
  21. 1 1
      misc/hooks/pre-commit-clang-format
  22. 48 32
      modules/mono/editor/bindings_generator.cpp
  23. 2 2
      modules/mono/mono_gd/support/android_support.cpp
  24. 3 0
      modules/xatlas_unwrap/register_types.cpp
  25. 2 0
      platform/android/file_access_android.cpp
  26. 6 4
      platform/android/java_godot_lib_jni.cpp
  27. 7 0
      platform/windows/detect.py
  28. 5 5
      platform/windows/joypad_windows.cpp
  29. 3 2
      platform/windows/windows_terminal_logger.cpp
  30. 2 2
      scene/gui/file_dialog.cpp
  31. 7 3
      servers/camera/camera_feed.cpp
  32. 3 3
      servers/camera/camera_feed.h
  33. 1 1
      thirdparty/README.md
  34. 17 0
      thirdparty/mbedtls/include/mbedtls/config.h
  35. 43 2
      thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
  36. 4 2
      thirdparty/mbedtls/include/mbedtls/entropy.h
  37. 55 3
      thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
  38. 15 3
      thirdparty/mbedtls/include/mbedtls/net_sockets.h
  39. 5 1
      thirdparty/mbedtls/include/mbedtls/rsa.h
  40. 3 0
      thirdparty/mbedtls/include/mbedtls/threading.h
  41. 4 4
      thirdparty/mbedtls/include/mbedtls/version.h
  42. 120 11
      thirdparty/mbedtls/library/base64.c
  43. 6 0
      thirdparty/mbedtls/library/bignum.c
  44. 8 8
      thirdparty/mbedtls/library/ctr_drbg.c
  45. 8 0
      thirdparty/mbedtls/library/ecdsa.c
  46. 11 0
      thirdparty/mbedtls/library/ecjpake.c
  47. 6 1
      thirdparty/mbedtls/library/entropy.c
  48. 12 8
      thirdparty/mbedtls/library/hmac_drbg.c
  49. 14 0
      thirdparty/mbedtls/library/net_sockets.c
  50. 11 11
      thirdparty/mbedtls/library/pkwrite.c
  51. 20 8
      thirdparty/mbedtls/library/rsa.c
  52. 6 0
      thirdparty/mbedtls/library/threading.c
  53. 3 0
      thirdparty/mbedtls/library/version_features.c

+ 7 - 4
SConstruct

@@ -247,13 +247,16 @@ for path in module_search_paths:
         # Built-in modules don't have nested modules,
         # Built-in modules don't have nested modules,
         # so save the time it takes to parse directories.
         # so save the time it takes to parse directories.
         modules = methods.detect_modules(path, recursive=False)
         modules = methods.detect_modules(path, recursive=False)
-    else:  # External.
+    else:  # Custom.
         modules = methods.detect_modules(path, env_base["custom_modules_recursive"])
         modules = methods.detect_modules(path, env_base["custom_modules_recursive"])
+        # Provide default include path for both the custom module search `path`
+        # and the base directory containing custom modules, as it may be different
+        # from the built-in "modules" name (e.g. "custom_modules/summator/summator.h"),
+        # so it can be referenced simply as `#include "summator/summator.h"`
+        # independently of where a module is located on user's filesystem.
+        env_base.Prepend(CPPPATH=[path, os.path.dirname(path)])
     # Note: custom modules can override built-in ones.
     # Note: custom modules can override built-in ones.
     modules_detected.update(modules)
     modules_detected.update(modules)
-    include_path = os.path.dirname(path)
-    if include_path:
-        env_base.Prepend(CPPPATH=[include_path])
 
 
 # Add module options
 # Add module options
 for name, path in modules_detected.items():
 for name, path in modules_detected.items():

+ 4 - 3
core/io/file_access_compressed.cpp

@@ -302,9 +302,10 @@ uint8_t FileAccessCompressed::get_8() const {
 	return ret;
 	return ret;
 }
 }
 int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
-
-	ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
-	ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
+	ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
+	ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
 
 
 	if (at_end) {
 	if (at_end) {
 		read_eof = true;
 		read_eof = true;

+ 4 - 2
core/io/file_access_encrypted.cpp

@@ -231,9 +231,11 @@ uint8_t FileAccessEncrypted::get_8() const {
 	pos++;
 	pos++;
 	return b;
 	return b;
 }
 }
-int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
 
 
-	ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
+int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
+	ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
 
 
 	int to_copy = MIN(p_length, data.size() - pos);
 	int to_copy = MIN(p_length, data.size() - pos);
 	for (int i = 0; i < to_copy; i++) {
 	for (int i = 0; i < to_copy; i++) {

+ 2 - 1
core/io/file_access_memory.cpp

@@ -150,7 +150,8 @@ uint8_t FileAccessMemory::get_8() const {
 }
 }
 
 
 int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
-
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 	ERR_FAIL_COND_V(!data, -1);
 	ERR_FAIL_COND_V(!data, -1);
 
 
 	int left = length - pos;
 	int left = length - pos;

+ 2 - 0
core/io/file_access_network.cpp

@@ -389,6 +389,8 @@ void FileAccessNetwork::_queue_page(int p_page) const {
 }
 }
 
 
 int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 
 
 	//bool eof=false;
 	//bool eof=false;
 	if (pos + p_length > total_size) {
 	if (pos + p_length > total_size) {

+ 2 - 0
core/io/file_access_pack.cpp

@@ -284,6 +284,8 @@ uint8_t FileAccessPack::get_8() const {
 }
 }
 
 
 int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 
 
 	if (eof)
 	if (eof)
 		return 0;
 		return 0;

+ 2 - 1
core/io/file_access_zip.cpp

@@ -332,7 +332,8 @@ uint8_t FileAccessZip::get_8() const {
 }
 }
 
 
 int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
-
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 	ERR_FAIL_COND_V(!zfile, -1);
 	ERR_FAIL_COND_V(!zfile, -1);
 	at_eof = unzeof(zfile);
 	at_eof = unzeof(zfile);
 	if (at_eof)
 	if (at_eof)

+ 2 - 1
core/os/file_access.cpp

@@ -399,7 +399,8 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
 }
 }
 
 
 int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const {
-
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 	int i = 0;
 	int i = 0;
 	for (i = 0; i < p_length && !eof_reached(); i++)
 	for (i = 0; i < p_length && !eof_reached(); i++)
 		p_dst[i] = get_8();
 		p_dst[i] = get_8();

+ 18 - 12
drivers/coreaudio/audio_driver_coreaudio.cpp

@@ -514,7 +514,8 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
 
 
 	UInt32 size = 0;
 	UInt32 size = 0;
 	AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &size);
 	AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &size);
-	AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size);
+	AudioDeviceID *audioDevices = (AudioDeviceID *)memalloc(size);
+	ERR_FAIL_NULL_V_MSG(audioDevices, list, "Out of memory.");
 	AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &size, audioDevices);
 	AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &size, audioDevices);
 
 
 	UInt32 deviceCount = size / sizeof(AudioDeviceID);
 	UInt32 deviceCount = size / sizeof(AudioDeviceID);
@@ -523,14 +524,15 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
 		prop.mSelector = kAudioDevicePropertyStreamConfiguration;
 		prop.mSelector = kAudioDevicePropertyStreamConfiguration;
 
 
 		AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, NULL, &size);
 		AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, NULL, &size);
-		AudioBufferList *bufferList = (AudioBufferList *)malloc(size);
+		AudioBufferList *bufferList = (AudioBufferList *)memalloc(size);
+		ERR_FAIL_NULL_V_MSG(bufferList, list, "Out of memory.");
 		AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, bufferList);
 		AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, bufferList);
 
 
 		UInt32 channelCount = 0;
 		UInt32 channelCount = 0;
 		for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
 		for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
 			channelCount += bufferList->mBuffers[j].mNumberChannels;
 			channelCount += bufferList->mBuffers[j].mNumberChannels;
 
 
-		free(bufferList);
+		memfree(bufferList);
 
 
 		if (channelCount >= 1) {
 		if (channelCount >= 1) {
 			CFStringRef cfname;
 			CFStringRef cfname;
@@ -542,17 +544,18 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
 
 
 			CFIndex length = CFStringGetLength(cfname);
 			CFIndex length = CFStringGetLength(cfname);
 			CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
 			CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
-			char *buffer = (char *)malloc(maxSize);
+			char *buffer = (char *)memalloc(maxSize);
+			ERR_FAIL_NULL_V_MSG(buffer, list, "Out of memory.");
 			if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
 			if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
 				// Append the ID to the name in case we have devices with duplicate name
 				// Append the ID to the name in case we have devices with duplicate name
 				list.push_back(String(buffer) + " (" + itos(audioDevices[i]) + ")");
 				list.push_back(String(buffer) + " (" + itos(audioDevices[i]) + ")");
 			}
 			}
 
 
-			free(buffer);
+			memfree(buffer);
 		}
 		}
 	}
 	}
 
 
-	free(audioDevices);
+	memfree(audioDevices);
 
 
 	return list;
 	return list;
 }
 }
@@ -570,7 +573,8 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
 
 
 		UInt32 size = 0;
 		UInt32 size = 0;
 		AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &size);
 		AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &size);
-		AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size);
+		AudioDeviceID *audioDevices = (AudioDeviceID *)memalloc(size);
+		ERR_FAIL_NULL_MSG(audioDevices, "Out of memory.");
 		AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &size, audioDevices);
 		AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &size, audioDevices);
 
 
 		UInt32 deviceCount = size / sizeof(AudioDeviceID);
 		UInt32 deviceCount = size / sizeof(AudioDeviceID);
@@ -579,14 +583,15 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
 			prop.mSelector = kAudioDevicePropertyStreamConfiguration;
 			prop.mSelector = kAudioDevicePropertyStreamConfiguration;
 
 
 			AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, NULL, &size);
 			AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, NULL, &size);
-			AudioBufferList *bufferList = (AudioBufferList *)malloc(size);
+			AudioBufferList *bufferList = (AudioBufferList *)memalloc(size);
+			ERR_FAIL_NULL_MSG(bufferList, "Out of memory.");
 			AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, bufferList);
 			AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, bufferList);
 
 
 			UInt32 channelCount = 0;
 			UInt32 channelCount = 0;
 			for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
 			for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
 				channelCount += bufferList->mBuffers[j].mNumberChannels;
 				channelCount += bufferList->mBuffers[j].mNumberChannels;
 
 
-			free(bufferList);
+			memfree(bufferList);
 
 
 			if (channelCount >= 1) {
 			if (channelCount >= 1) {
 				CFStringRef cfname;
 				CFStringRef cfname;
@@ -598,7 +603,8 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
 
 
 				CFIndex length = CFStringGetLength(cfname);
 				CFIndex length = CFStringGetLength(cfname);
 				CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
 				CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
-				char *buffer = (char *)malloc(maxSize);
+				char *buffer = (char *)memalloc(maxSize);
+				ERR_FAIL_NULL_MSG(buffer, "Out of memory.");
 				if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
 				if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
 					String name = String(buffer) + " (" + itos(audioDevices[i]) + ")";
 					String name = String(buffer) + " (" + itos(audioDevices[i]) + ")";
 					if (name == device) {
 					if (name == device) {
@@ -607,11 +613,11 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
 					}
 					}
 				}
 				}
 
 
-				free(buffer);
+				memfree(buffer);
 			}
 			}
 		}
 		}
 
 
-		free(audioDevices);
+		memfree(audioDevices);
 	}
 	}
 
 
 	if (!found) {
 	if (!found) {

+ 2 - 1
drivers/unix/file_access_unix.cpp

@@ -248,7 +248,8 @@ uint8_t FileAccessUnix::get_8() const {
 }
 }
 
 
 int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
-
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 	ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
 	ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
 	int read = fread(p_dst, 1, p_length, f);
 	int read = fread(p_dst, 1, p_length, f);
 	check_errors();
 	check_errors();

+ 2 - 1
drivers/windows/file_access_windows.cpp

@@ -259,7 +259,8 @@ uint8_t FileAccessWindows::get_8() const {
 }
 }
 
 
 int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessWindows::get_buffer(uint8_t *p_dst, int p_length) const {
-
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 	ERR_FAIL_COND_V(!f, -1);
 	ERR_FAIL_COND_V(!f, -1);
 	if (flags == READ_WRITE || flags == WRITE_READ) {
 	if (flags == READ_WRITE || flags == WRITE_READ) {
 		if (prev_op == WRITE) {
 		if (prev_op == WRITE) {

+ 2 - 2
editor/editor_file_dialog.cpp

@@ -1105,9 +1105,9 @@ EditorFileDialog::Access EditorFileDialog::get_access() const {
 
 
 void EditorFileDialog::_make_dir_confirm() {
 void EditorFileDialog::_make_dir_confirm() {
 
 
-	Error err = dir_access->make_dir(makedirname->get_text());
+	Error err = dir_access->make_dir(makedirname->get_text().strip_edges());
 	if (err == OK) {
 	if (err == OK) {
-		dir_access->change_dir(makedirname->get_text());
+		dir_access->change_dir(makedirname->get_text().strip_edges());
 		invalidate();
 		invalidate();
 		update_filters();
 		update_filters();
 		update_dir();
 		update_dir();

+ 8 - 5
editor/editor_node.cpp

@@ -2340,11 +2340,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
 				_scene_tab_changed(tab_closing);
 				_scene_tab_changed(tab_closing);
 
 
 				if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) {
 				if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) {
-					String scene_filename = editor_data.get_edited_scene_root(tab_closing)->get_filename();
-					save_confirmation->get_ok()->set_text(TTR("Save & Close"));
-					save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene"));
-					save_confirmation->popup_centered_minsize();
-					break;
+					Node *scene_root = editor_data.get_edited_scene_root(tab_closing);
+					if (scene_root) {
+						String scene_filename = scene_root->get_filename();
+						save_confirmation->get_ok()->set_text(TTR("Save & Close"));
+						save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene"));
+						save_confirmation->popup_centered_minsize();
+						break;
+					}
 				}
 				}
 			} else if (p_option == FILE_CLOSE) {
 			} else if (p_option == FILE_CLOSE) {
 				tab_closing = editor_data.get_edited_scene();
 				tab_closing = editor_data.get_edited_scene();

+ 1 - 1
editor/editor_properties.cpp

@@ -2702,7 +2702,7 @@ void EditorPropertyResource::update_property() {
 				sub_inspector->set_use_doc_hints(true);
 				sub_inspector->set_use_doc_hints(true);
 
 
 				sub_inspector->set_sub_inspector(true);
 				sub_inspector->set_sub_inspector(true);
-				sub_inspector->set_enable_capitalize_paths(true);
+				sub_inspector->set_enable_capitalize_paths(bool(EDITOR_GET("interface/inspector/capitalize_properties")));
 
 
 				sub_inspector->connect("property_keyed", this, "_sub_inspector_property_keyed");
 				sub_inspector->connect("property_keyed", this, "_sub_inspector_property_keyed");
 				sub_inspector->connect("resource_selected", this, "_sub_inspector_resource_selected");
 				sub_inspector->connect("resource_selected", this, "_sub_inspector_resource_selected");

+ 6 - 2
editor/editor_spin_slider.cpp

@@ -185,7 +185,9 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
 		if (mousewheel_over_grabber)
 		if (mousewheel_over_grabber)
 			return;
 			return;
 
 
-		float grabbing_ofs = (grabber->get_transform().xform(mm->get_position()).x - grabbing_from) / float(grabber_range);
+		float scale_x = get_global_transform_with_canvas().get_scale().x;
+		ERR_FAIL_COND(Math::is_zero_approx(scale_x));
+		float grabbing_ofs = (grabber->get_transform().xform(mm->get_position()).x - grabbing_from) / float(grabber_range) / scale_x;
 		set_as_ratio(grabbing_ratio + grabbing_ofs);
 		set_as_ratio(grabbing_ratio + grabbing_ofs);
 		update();
 		update();
 	}
 	}
@@ -311,8 +313,10 @@ void EditorSpinSlider::_notification(int p_what) {
 					grabber->set_texture(grabber_tex);
 					grabber->set_texture(grabber_tex);
 				}
 				}
 
 
+				Vector2 scale = get_global_transform_with_canvas().get_scale();
+				grabber->set_scale(scale);
 				grabber->set_size(Size2(0, 0));
 				grabber->set_size(Size2(0, 0));
-				grabber->set_position(get_global_position() + grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5);
+				grabber->set_position(get_global_position() + (grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5) * scale);
 
 
 				if (mousewheel_over_grabber) {
 				if (mousewheel_over_grabber) {
 					Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size);
 					Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size);

+ 2 - 2
editor/plugins/abstract_polygon_2d_editor.cpp

@@ -686,12 +686,12 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) {
 		edited_point = PosVertex();
 		edited_point = PosVertex();
 		hover_point = Vertex();
 		hover_point = Vertex();
 		selected_point = Vertex();
 		selected_point = Vertex();
-
-		canvas_item_editor->update_viewport();
 	} else {
 	} else {
 
 
 		_set_node(NULL);
 		_set_node(NULL);
 	}
 	}
+
+	canvas_item_editor->update_viewport();
 }
 }
 
 
 void AbstractPolygon2DEditor::_bind_methods() {
 void AbstractPolygon2DEditor::_bind_methods() {

+ 19 - 12
editor/plugins/asset_library_editor_plugin.cpp

@@ -626,6 +626,24 @@ void EditorAssetLibrary::_notification(int p_what) {
 			filter->set_right_icon(get_icon("Search", "EditorIcons"));
 			filter->set_right_icon(get_icon("Search", "EditorIcons"));
 			filter->set_clear_button_enabled(true);
 			filter->set_clear_button_enabled(true);
 		} break;
 		} break;
+
+		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+			_update_repository_options();
+		} break;
+	}
+}
+
+void EditorAssetLibrary::_update_repository_options() {
+	Dictionary default_urls;
+	default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api";
+	default_urls["localhost"] = "http://127.0.0.1/asset-library/api";
+	Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true);
+	repository->clear();
+	Array keys = available_urls.keys();
+	for (int i = 0; i < available_urls.size(); i++) {
+		String key = keys[i];
+		repository->add_item(key);
+		repository->set_item_metadata(i, available_urls[key]);
 	}
 	}
 }
 }
 
 
@@ -1432,18 +1450,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
 	search_hb2->add_child(memnew(Label(TTR("Site:") + " ")));
 	search_hb2->add_child(memnew(Label(TTR("Site:") + " ")));
 	repository = memnew(OptionButton);
 	repository = memnew(OptionButton);
 
 
-	{
-		Dictionary default_urls;
-		default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api";
-		default_urls["localhost"] = "http://127.0.0.1/asset-library/api";
-		Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true);
-		Array keys = available_urls.keys();
-		for (int i = 0; i < available_urls.size(); i++) {
-			String key = keys[i];
-			repository->add_item(key);
-			repository->set_item_metadata(i, available_urls[key]);
-		}
-	}
+	_update_repository_options();
 
 
 	repository->connect("item_selected", this, "_repository_changed");
 	repository->connect("item_selected", this, "_repository_changed");
 
 

+ 1 - 0
editor/plugins/asset_library_editor_plugin.h

@@ -179,6 +179,7 @@ class EditorAssetLibrary : public PanelContainer {
 
 
 	void _asset_open();
 	void _asset_open();
 	void _asset_file_selected(const String &p_file);
 	void _asset_file_selected(const String &p_file);
+	void _update_repository_options();
 
 
 	PanelContainer *library_scroll_bg;
 	PanelContainer *library_scroll_bg;
 	ScrollContainer *library_scroll;
 	ScrollContainer *library_scroll;

+ 3 - 4
editor/plugins/spatial_editor_plugin.cpp

@@ -1847,10 +1847,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 
 
 		} else if (m->get_button_mask() & BUTTON_MASK_MIDDLE) {
 		} else if (m->get_button_mask() & BUTTON_MASK_MIDDLE) {
 
 
+			const int mod = _get_key_modifier(m);
 			if (nav_scheme == NAVIGATION_GODOT) {
 			if (nav_scheme == NAVIGATION_GODOT) {
-
-				const int mod = _get_key_modifier(m);
-
 				if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
 				if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
 					nav_mode = NAVIGATION_PAN;
 					nav_mode = NAVIGATION_PAN;
 				} else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) {
 				} else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) {
@@ -1861,8 +1859,9 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 				}
 				}
 
 
 			} else if (nav_scheme == NAVIGATION_MAYA) {
 			} else if (nav_scheme == NAVIGATION_MAYA) {
-				if (m->get_alt())
+				if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
 					nav_mode = NAVIGATION_PAN;
 					nav_mode = NAVIGATION_PAN;
+				}
 			}
 			}
 
 
 		} else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) {
 		} else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) {

+ 2 - 2
editor/scene_tree_editor.cpp

@@ -635,8 +635,7 @@ void SceneTreeEditor::_selected_changed() {
 }
 }
 
 
 void SceneTreeEditor::_deselect_items() {
 void SceneTreeEditor::_deselect_items() {
-
-	// Clear currently elected items in scene tree dock.
+	// Clear currently selected items in scene tree dock.
 	if (editor_selection) {
 	if (editor_selection) {
 		editor_selection->clear();
 		editor_selection->clear();
 		emit_signal("node_changed");
 		emit_signal("node_changed");
@@ -1196,6 +1195,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
 	tree->set_begin(Point2(0, p_label ? 18 : 0));
 	tree->set_begin(Point2(0, p_label ? 18 : 0));
 	tree->set_end(Point2(0, 0));
 	tree->set_end(Point2(0, 0));
 	tree->add_constant_override("button_margin", 0);
 	tree->add_constant_override("button_margin", 0);
+	tree->set_allow_reselect(true);
 
 
 	add_child(tree);
 	add_child(tree);
 
 

+ 1 - 1
misc/hooks/pre-commit-clang-format

@@ -103,7 +103,7 @@ CLANG_FORMAT_VERSION="$(clang-format --version | cut -d' ' -f3)"
 CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d'.' -f1)"
 CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d'.' -f1)"
 
 
 if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then
 if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then
-    echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $CLANG_FORMAT_MAJOR.x.x)."
+    echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x)."
     echo "         Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
     echo "         Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
 fi
 fi
 
 

+ 48 - 32
modules/mono/editor/bindings_generator.cpp

@@ -3067,12 +3067,45 @@ void BindingsGenerator::_initialize() {
 	initialized = true;
 	initialized = true;
 }
 }
 
 
+static String generate_all_glue_option = "--generate-mono-glue";
+static String generate_cs_glue_option = "--generate-mono-cs-glue";
+static String generate_cpp_glue_option = "--generate-mono-cpp-glue";
+
+static void handle_cmdline_options(String glue_dir_path, String cs_dir_path, String cpp_dir_path) {
+	BindingsGenerator bindings_generator;
+	bindings_generator.set_log_print_enabled(true);
+
+	if (!bindings_generator.is_initialized()) {
+		ERR_PRINT("Failed to initialize the bindings generator");
+		return;
+	}
+
+	if (glue_dir_path.length()) {
+		if (bindings_generator.generate_glue(glue_dir_path) != OK) {
+			ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue.");
+		}
+
+		if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) {
+			ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API.");
+		}
+	}
+
+	if (cs_dir_path.length()) {
+		if (bindings_generator.generate_cs_api(cs_dir_path) != OK) {
+			ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API.");
+		}
+	}
+
+	if (cpp_dir_path.length()) {
+		if (bindings_generator.generate_glue(cpp_dir_path) != OK) {
+			ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
+		}
+	}
+}
+
 void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
 void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
 
 
 	const int NUM_OPTIONS = 2;
 	const int NUM_OPTIONS = 2;
-	String generate_all_glue_option = "--generate-mono-glue";
-	String generate_cs_glue_option = "--generate-mono-cs-glue";
-	String generate_cpp_glue_option = "--generate-mono-cpp-glue";
 
 
 	String glue_dir_path;
 	String glue_dir_path;
 	String cs_dir_path;
 	String cs_dir_path;
@@ -3080,6 +3113,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 
 
 	int options_left = NUM_OPTIONS;
 	int options_left = NUM_OPTIONS;
 
 
+	bool exit_godot = false;
+
 	const List<String>::Element *elem = p_cmdline_args.front();
 	const List<String>::Element *elem = p_cmdline_args.front();
 
 
 	while (elem && options_left) {
 	while (elem && options_left) {
@@ -3090,7 +3125,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 				glue_dir_path = path_elem->get();
 				glue_dir_path = path_elem->get();
 				elem = elem->next();
 				elem = elem->next();
 			} else {
 			} else {
-				ERR_PRINTS(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue').");
+				ERR_PRINT(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue').");
+				exit_godot = true;
 			}
 			}
 
 
 			--options_left;
 			--options_left;
@@ -3101,7 +3137,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 				cs_dir_path = path_elem->get();
 				cs_dir_path = path_elem->get();
 				elem = elem->next();
 				elem = elem->next();
 			} else {
 			} else {
-				ERR_PRINTS(generate_cs_glue_option + ": No output directory specified.");
+				ERR_PRINT(generate_cs_glue_option + ": No output directory specified.");
+				exit_godot = true;
 			}
 			}
 
 
 			--options_left;
 			--options_left;
@@ -3112,7 +3149,8 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 				cpp_dir_path = path_elem->get();
 				cpp_dir_path = path_elem->get();
 				elem = elem->next();
 				elem = elem->next();
 			} else {
 			} else {
-				ERR_PRINTS(generate_cpp_glue_option + ": No output directory specified.");
+				ERR_PRINT(generate_cpp_glue_option + ": No output directory specified.");
+				exit_godot = true;
 			}
 			}
 
 
 			--options_left;
 			--options_left;
@@ -3122,33 +3160,11 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
 	}
 	}
 
 
 	if (glue_dir_path.length() || cs_dir_path.length() || cpp_dir_path.length()) {
 	if (glue_dir_path.length() || cs_dir_path.length() || cpp_dir_path.length()) {
-		BindingsGenerator bindings_generator;
-		bindings_generator.set_log_print_enabled(true);
-
-		if (!bindings_generator.initialized) {
-			ERR_PRINTS("Failed to initialize the bindings generator");
-			Main::cleanup(true);
-			::exit(0);
-		}
-
-		if (glue_dir_path.length()) {
-			if (bindings_generator.generate_glue(glue_dir_path) != OK)
-				ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C++ glue.");
-
-			if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK)
-				ERR_PRINTS(generate_all_glue_option + ": Failed to generate the C# API.");
-		}
-
-		if (cs_dir_path.length()) {
-			if (bindings_generator.generate_cs_api(cs_dir_path) != OK)
-				ERR_PRINTS(generate_cs_glue_option + ": Failed to generate the C# API.");
-		}
-
-		if (cpp_dir_path.length()) {
-			if (bindings_generator.generate_glue(cpp_dir_path) != OK)
-				ERR_PRINTS(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
-		}
+		handle_cmdline_options(glue_dir_path, cs_dir_path, cpp_dir_path);
+		exit_godot = true;
+	}
 
 
+	if (exit_godot) {
 		// Exit once done
 		// Exit once done
 		Main::cleanup(true);
 		Main::cleanup(true);
 		::exit(0);
 		::exit(0);

+ 2 - 2
modules/mono/mono_gd/support/android_support.cpp

@@ -416,8 +416,7 @@ GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char
 	if (r_value) {
 	if (r_value) {
 		if (len >= 0) {
 		if (len >= 0) {
 			*r_value = (char *)malloc(len + 1);
 			*r_value = (char *)malloc(len + 1);
-			if (!*r_value)
-				return -1;
+			ERR_FAIL_NULL_V_MSG(*r_value, -1, "Out of memory.");
 			memcpy(*r_value, prop_value_str, len);
 			memcpy(*r_value, prop_value_str, len);
 			(*r_value)[len] = '\0';
 			(*r_value)[len] = '\0';
 		} else {
 		} else {
@@ -638,6 +637,7 @@ GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array)
 	if (dns_servers_count > 0) {
 	if (dns_servers_count > 0) {
 		size_t ret_size = sizeof(char *) * (size_t)dns_servers_count;
 		size_t ret_size = sizeof(char *) * (size_t)dns_servers_count;
 		*r_dns_servers_array = malloc(ret_size); // freed by the BCL
 		*r_dns_servers_array = malloc(ret_size); // freed by the BCL
+		ERR_FAIL_NULL_MSG(*r_dns_servers_array, "Out of memory.");
 		memcpy(*r_dns_servers_array, dns_servers, ret_size);
 		memcpy(*r_dns_servers_array, dns_servers, ret_size);
 	}
 	}
 
 

+ 3 - 0
modules/xatlas_unwrap/register_types.cpp

@@ -85,8 +85,11 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
 	const xatlas::Mesh &output = atlas->meshes[0];
 	const xatlas::Mesh &output = atlas->meshes[0];
 
 
 	*r_vertex = (int *)malloc(sizeof(int) * output.vertexCount);
 	*r_vertex = (int *)malloc(sizeof(int) * output.vertexCount);
+	ERR_FAIL_NULL_V_MSG(*r_vertex, false, "Out of memory.");
 	*r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2);
 	*r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2);
+	ERR_FAIL_NULL_V_MSG(*r_uv, false, "Out of memory.");
 	*r_index = (int *)malloc(sizeof(int) * output.indexCount);
 	*r_index = (int *)malloc(sizeof(int) * output.indexCount);
+	ERR_FAIL_NULL_V_MSG(*r_index, false, "Out of memory.");
 
 
 	float max_x = 0;
 	float max_x = 0;
 	float max_y = 0;
 	float max_y = 0;

+ 2 - 0
platform/android/file_access_android.cpp

@@ -125,6 +125,8 @@ uint8_t FileAccessAndroid::get_8() const {
 }
 }
 
 
 int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const {
 int FileAccessAndroid::get_buffer(uint8_t *p_dst, int p_length) const {
+	ERR_FAIL_COND_V(!p_dst, -1);
+	ERR_FAIL_COND_V(p_length < 0, -1);
 
 
 	off_t r = AAsset_read(a, p_dst, p_length);
 	off_t r = AAsset_read(a, p_dst, p_length);
 
 

+ 6 - 4
platform/android/java_godot_lib_jni.cpp

@@ -172,9 +172,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
 	if (p_cmdline) {
 	if (p_cmdline) {
 		cmdlen = env->GetArrayLength(p_cmdline);
 		cmdlen = env->GetArrayLength(p_cmdline);
 		if (cmdlen) {
 		if (cmdlen) {
-			cmdline = (const char **)malloc((cmdlen + 1) * sizeof(const char *));
+			cmdline = (const char **)memalloc((cmdlen + 1) * sizeof(const char *));
+			ERR_FAIL_NULL_MSG(cmdline, "Out of memory.");
 			cmdline[cmdlen] = NULL;
 			cmdline[cmdlen] = NULL;
-			j_cmdline = (jstring *)malloc(cmdlen * sizeof(jstring));
+			j_cmdline = (jstring *)memalloc(cmdlen * sizeof(jstring));
+			ERR_FAIL_NULL_MSG(j_cmdline, "Out of memory.");
 
 
 			for (int i = 0; i < cmdlen; i++) {
 			for (int i = 0; i < cmdlen; i++) {
 
 
@@ -193,9 +195,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
 			for (int i = 0; i < cmdlen; ++i) {
 			for (int i = 0; i < cmdlen; ++i) {
 				env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]);
 				env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]);
 			}
 			}
-			free(j_cmdline);
+			memfree(j_cmdline);
 		}
 		}
-		free(cmdline);
+		memfree(cmdline);
 	}
 	}
 
 
 	if (err != OK) {
 	if (err != OK) {

+ 7 - 0
platform/windows/detect.py

@@ -71,6 +71,7 @@ def get_opts():
         BoolVariable("use_llvm", "Use the LLVM compiler", False),
         BoolVariable("use_llvm", "Use the LLVM compiler", False),
         BoolVariable("use_thinlto", "Use ThinLTO", False),
         BoolVariable("use_thinlto", "Use ThinLTO", False),
         BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
         BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
+        BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
     ]
     ]
 
 
 
 
@@ -283,6 +284,12 @@ def configure_msvc(env, manual_msvc_config):
         env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
         env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
         env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
         env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
 
 
+    # Sanitizers
+    if env["use_asan"]:
+        env.extra_suffix += ".s"
+        env.Append(LINKFLAGS=["/INFERASANLIBS"])
+        env.Append(CCFLAGS=["/fsanitize=address"])
+
     # Incremental linking fix
     # Incremental linking fix
     env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
     env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
     env["BUILDERS"]["Program"] = methods.precious_program
     env["BUILDERS"]["Program"] = methods.precious_program

+ 5 - 5
platform/windows/joypad_windows.cpp

@@ -115,11 +115,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
 	if (GetRawInputDeviceList(NULL, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
 	if (GetRawInputDeviceList(NULL, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
 		return false;
 		return false;
 	}
 	}
-	dev_list = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
-	if (!dev_list) return false;
+	dev_list = (PRAWINPUTDEVICELIST)memalloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
+	ERR_FAIL_NULL_V_MSG(dev_list, false, "Out of memory.");
 
 
 	if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
 	if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
-		free(dev_list);
+		memfree(dev_list);
 		return false;
 		return false;
 	}
 	}
 	for (unsigned int i = 0; i < dev_list_count; i++) {
 	for (unsigned int i = 0; i < dev_list_count; i++) {
@@ -136,11 +136,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
 				(GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, &dev_name, &nameSize) != (UINT)-1) &&
 				(GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, &dev_name, &nameSize) != (UINT)-1) &&
 				(strstr(dev_name, "IG_") != NULL)) {
 				(strstr(dev_name, "IG_") != NULL)) {
 
 
-			free(dev_list);
+			memfree(dev_list);
 			return true;
 			return true;
 		}
 		}
 	}
 	}
-	free(dev_list);
+	memfree(dev_list);
 	return false;
 	return false;
 }
 }
 
 

+ 3 - 2
platform/windows/windows_terminal_logger.cpp

@@ -53,7 +53,8 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
 	if (wlen < 0)
 	if (wlen < 0)
 		return;
 		return;
 
 
-	wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
+	wchar_t *wbuf = (wchar_t *)memalloc((len + 1) * sizeof(wchar_t));
+	ERR_FAIL_NULL_MSG(wbuf, "Out of memory.");
 	MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
 	MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
 	wbuf[wlen] = 0;
 	wbuf[wlen] = 0;
 
 
@@ -62,7 +63,7 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
 	else
 	else
 		wprintf(L"%ls", wbuf);
 		wprintf(L"%ls", wbuf);
 
 
-	free(wbuf);
+	memfree(wbuf);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	fflush(stdout);
 	fflush(stdout);

+ 2 - 2
scene/gui/file_dialog.cpp

@@ -761,9 +761,9 @@ FileDialog::Access FileDialog::get_access() const {
 
 
 void FileDialog::_make_dir_confirm() {
 void FileDialog::_make_dir_confirm() {
 
 
-	Error err = dir_access->make_dir(makedirname->get_text());
+	Error err = dir_access->make_dir(makedirname->get_text().strip_edges());
 	if (err == OK) {
 	if (err == OK) {
-		dir_access->change_dir(makedirname->get_text());
+		dir_access->change_dir(makedirname->get_text().strip_edges());
 		invalidate();
 		invalidate();
 		update_filters();
 		update_filters();
 		update_dir();
 		update_dir();

+ 7 - 3
servers/camera/camera_feed.cpp

@@ -172,7 +172,8 @@ CameraFeed::~CameraFeed() {
 	vs->free(texture[CameraServer::FEED_CBCR_IMAGE]);
 	vs->free(texture[CameraServer::FEED_CBCR_IMAGE]);
 }
 }
 
 
-void CameraFeed::set_RGB_img(Ref<Image> p_rgb_img) {
+void CameraFeed::set_RGB_img(const Ref<Image> &p_rgb_img) {
+	ERR_FAIL_COND(p_rgb_img.is_null());
 	if (active) {
 	if (active) {
 		VisualServer *vs = VisualServer::get_singleton();
 		VisualServer *vs = VisualServer::get_singleton();
 
 
@@ -192,7 +193,8 @@ void CameraFeed::set_RGB_img(Ref<Image> p_rgb_img) {
 	}
 	}
 }
 }
 
 
-void CameraFeed::set_YCbCr_img(Ref<Image> p_ycbcr_img) {
+void CameraFeed::set_YCbCr_img(const Ref<Image> &p_ycbcr_img) {
+	ERR_FAIL_COND(p_ycbcr_img.is_null());
 	if (active) {
 	if (active) {
 		VisualServer *vs = VisualServer::get_singleton();
 		VisualServer *vs = VisualServer::get_singleton();
 
 
@@ -212,7 +214,9 @@ void CameraFeed::set_YCbCr_img(Ref<Image> p_ycbcr_img) {
 	}
 	}
 }
 }
 
 
-void CameraFeed::set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_img) {
+void CameraFeed::set_YCbCr_imgs(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img) {
+	ERR_FAIL_COND(p_y_img.is_null());
+	ERR_FAIL_COND(p_cbcr_img.is_null());
 	if (active) {
 	if (active) {
 		VisualServer *vs = VisualServer::get_singleton();
 		VisualServer *vs = VisualServer::get_singleton();
 
 

+ 3 - 3
servers/camera/camera_feed.h

@@ -100,9 +100,9 @@ public:
 	virtual ~CameraFeed();
 	virtual ~CameraFeed();
 
 
 	FeedDataType get_datatype() const;
 	FeedDataType get_datatype() const;
-	void set_RGB_img(Ref<Image> p_rgb_img);
-	void set_YCbCr_img(Ref<Image> p_ycbcr_img);
-	void set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_img);
+	void set_RGB_img(const Ref<Image> &p_rgb_img);
+	void set_YCbCr_img(const Ref<Image> &p_ycbcr_img);
+	void set_YCbCr_imgs(const Ref<Image> &p_y_img, const Ref<Image> &p_cbcr_img);
 	void allocate_texture(int p_width, int p_height, Image::Format p_format, VisualServer::TextureType p_texture_type, FeedDataType p_data_type);
 	void allocate_texture(int p_width, int p_height, Image::Format p_format, VisualServer::TextureType p_texture_type, FeedDataType p_data_type);
 
 
 	virtual bool activate_feed();
 	virtual bool activate_feed();

+ 1 - 1
thirdparty/README.md

@@ -264,7 +264,7 @@ changes are marked with `// -- GODOT --` comments.
 ## mbedtls
 ## mbedtls
 
 
 - Upstream: https://tls.mbed.org/
 - Upstream: https://tls.mbed.org/
-- Version: 2.16.9 (3fac0bae4a50113989b3d015cd2d948f51a6d9ac, 2020)
+- Version: 2.16.10 (d61fa61bef06b64132e3490543c81b8ee40fbee3, 2021)
 - License: Apache 2.0
 - License: Apache 2.0
 
 
 File extracted from upstream release tarball:
 File extracted from upstream release tarball:

+ 17 - 0
thirdparty/mbedtls/include/mbedtls/config.h

@@ -1746,6 +1746,23 @@
  */
  */
 //#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT
 //#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT
 
 
+/**
+ * \def MBEDTLS_TEST_HOOKS
+ *
+ * Enable features for invasive testing such as introspection functions and
+ * hooks for fault injection. This enables additional unit tests.
+ *
+ * Merely enabling this feature should not change the behavior of the product.
+ * It only adds new code, and new branching points where the default behavior
+ * is the same as when this feature is disabled.
+ * However, this feature increases the attack surface: there is an added
+ * risk of vulnerabilities, and more gadgets that can make exploits easier.
+ * Therefore this feature must never be enabled in production.
+ *
+ * Uncomment to enable invasive tests.
+ */
+//#define MBEDTLS_TEST_HOOKS
+
 /**
 /**
  * \def MBEDTLS_THREADING_ALT
  * \def MBEDTLS_THREADING_ALT
  *
  *

+ 43 - 2
thirdparty/mbedtls/include/mbedtls/ctr_drbg.h

@@ -214,6 +214,13 @@ typedef struct mbedtls_ctr_drbg_context
     void *p_entropy;            /*!< The context for the entropy function. */
     void *p_entropy;            /*!< The context for the entropy function. */
 
 
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
+    /* Invariant: the mutex is initialized if and only if f_entropy != NULL.
+     * This means that the mutex is initialized during the initial seeding
+     * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free().
+     *
+     * Note that this invariant may change without notice. Do not rely on it
+     * and do not access the mutex directly in application code.
+     */
     mbedtls_threading_mutex_t mutex;
     mbedtls_threading_mutex_t mutex;
 #endif
 #endif
 }
 }
@@ -277,6 +284,15 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
  *                      device.
  *                      device.
  */
  */
 #endif
 #endif
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      after this function returns successfully,
+ *                      it is safe to call mbedtls_ctr_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
 /**
 /**
  * \param ctx           The CTR_DRBG context to seed.
  * \param ctx           The CTR_DRBG context to seed.
  *                      It must have been initialized with
  *                      It must have been initialized with
@@ -286,6 +302,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
  *                      the same context unless you call
  *                      the same context unless you call
  *                      mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
  *                      mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
  *                      again first.
  *                      again first.
+ *                      After a failed call to mbedtls_ctr_drbg_seed(),
+ *                      you must call mbedtls_ctr_drbg_free().
  * \param f_entropy     The entropy callback, taking as arguments the
  * \param f_entropy     The entropy callback, taking as arguments the
  *                      \p p_entropy context, the buffer to fill, and the
  *                      \p p_entropy context, the buffer to fill, and the
  *                      length of the buffer.
  *                      length of the buffer.
@@ -377,6 +395,11 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
  * \brief               This function reseeds the CTR_DRBG context, that is
  * \brief               This function reseeds the CTR_DRBG context, that is
  *                      extracts data from the entropy source.
  *                      extracts data from the entropy source.
  *
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx           The CTR_DRBG context.
  * \param ctx           The CTR_DRBG context.
  * \param additional    Additional data to add to the state. Can be \c NULL.
  * \param additional    Additional data to add to the state. Can be \c NULL.
  * \param len           The length of the additional data.
  * \param len           The length of the additional data.
@@ -394,6 +417,11 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
 /**
 /**
  * \brief              This function updates the state of the CTR_DRBG context.
  * \brief              This function updates the state of the CTR_DRBG context.
  *
  *
+ * \note               This function is not thread-safe. It is not safe
+ *                     to call this function if another thread might be
+ *                     concurrently obtaining random numbers from the same
+ *                     context or updating or reseeding the same context.
+ *
  * \param ctx          The CTR_DRBG context.
  * \param ctx          The CTR_DRBG context.
  * \param additional   The data to update the state with. This must not be
  * \param additional   The data to update the state with. This must not be
  *                     \c NULL unless \p add_len is \c 0.
  *                     \c NULL unless \p add_len is \c 0.
@@ -417,6 +445,11 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
  * This function automatically reseeds if the reseed counter is exceeded
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
  * or prediction resistance is enabled.
  *
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
  * \param output        The buffer to fill.
@@ -445,8 +478,16 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
  *
  *
  * This function automatically reseeds if the reseed counter is exceeded
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
  * or prediction resistance is enabled.
- *
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      it is safe to call mbedtls_ctr_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
  * \param output        The buffer to fill.

+ 4 - 2
thirdparty/mbedtls/include/mbedtls/entropy.h

@@ -147,13 +147,15 @@ mbedtls_entropy_source_state;
  */
  */
 typedef struct mbedtls_entropy_context
 typedef struct mbedtls_entropy_context
 {
 {
-    int accumulator_started;
+    int accumulator_started; /* 0 after init.
+                              * 1 after the first update.
+                              * -1 after free. */
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
     mbedtls_sha512_context  accumulator;
     mbedtls_sha512_context  accumulator;
 #else
 #else
     mbedtls_sha256_context  accumulator;
     mbedtls_sha256_context  accumulator;
 #endif
 #endif
-    int             source_count;
+    int             source_count; /* Number of entries used in source. */
     mbedtls_entropy_source_state    source[MBEDTLS_ENTROPY_MAX_SOURCES];
     mbedtls_entropy_source_state    source[MBEDTLS_ENTROPY_MAX_SOURCES];
 #if defined(MBEDTLS_HAVEGE_C)
 #if defined(MBEDTLS_HAVEGE_C)
     mbedtls_havege_state    havege_data;
     mbedtls_havege_state    havege_data;

+ 55 - 3
thirdparty/mbedtls/include/mbedtls/hmac_drbg.h

@@ -128,6 +128,14 @@ typedef struct mbedtls_hmac_drbg_context
     void *p_entropy;            /*!< context for the entropy function        */
     void *p_entropy;            /*!< context for the entropy function        */
 
 
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
+    /* Invariant: the mutex is initialized if and only if
+     * md_ctx->md_info != NULL. This means that the mutex is initialized
+     * during the initial seeding in mbedtls_hmac_drbg_seed() or
+     * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free().
+     *
+     * Note that this invariant may change without notice. Do not rely on it
+     * and do not access the mutex directly in application code.
+     */
     mbedtls_threading_mutex_t mutex;
     mbedtls_threading_mutex_t mutex;
 #endif
 #endif
 } mbedtls_hmac_drbg_context;
 } mbedtls_hmac_drbg_context;
@@ -177,7 +185,17 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
  * \note                During the initial seeding, this function calls
  * \note                During the initial seeding, this function calls
  *                      the entropy source to obtain a nonce
  *                      the entropy source to obtain a nonce
  *                      whose length is half the entropy length.
  *                      whose length is half the entropy length.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      after this function returns successfully,
+ *                      it is safe to call mbedtls_hmac_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param ctx           HMAC_DRBG context to be seeded.
  * \param ctx           HMAC_DRBG context to be seeded.
  * \param md_info       MD algorithm to use for HMAC_DRBG.
  * \param md_info       MD algorithm to use for HMAC_DRBG.
  * \param f_entropy     The entropy callback, taking as arguments the
  * \param f_entropy     The entropy callback, taking as arguments the
@@ -216,7 +234,17 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
  *
  *
  * This function is meant for use in algorithms that need a pseudorandom
  * This function is meant for use in algorithms that need a pseudorandom
  * input such as deterministic ECDSA.
  * input such as deterministic ECDSA.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      after this function returns successfully,
+ *                      it is safe to call mbedtls_hmac_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param ctx           HMAC_DRBG context to be initialised.
  * \param ctx           HMAC_DRBG context to be initialised.
  * \param md_info       MD algorithm to use for HMAC_DRBG.
  * \param md_info       MD algorithm to use for HMAC_DRBG.
  * \param data          Concatenation of the initial entropy string and
  * \param data          Concatenation of the initial entropy string and
@@ -279,6 +307,11 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
 /**
 /**
  * \brief               This function updates the state of the HMAC_DRBG context.
  * \brief               This function updates the state of the HMAC_DRBG context.
  *
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx           The HMAC_DRBG context.
  * \param ctx           The HMAC_DRBG context.
  * \param additional    The data to update the state with.
  * \param additional    The data to update the state with.
  *                      If this is \c NULL, there is no additional data.
  *                      If this is \c NULL, there is no additional data.
@@ -295,6 +328,11 @@ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
  * \brief               This function reseeds the HMAC_DRBG context, that is
  * \brief               This function reseeds the HMAC_DRBG context, that is
  *                      extracts data from the entropy source.
  *                      extracts data from the entropy source.
  *
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx           The HMAC_DRBG context.
  * \param ctx           The HMAC_DRBG context.
  * \param additional    Additional data to add to the state.
  * \param additional    Additional data to add to the state.
  *                      If this is \c NULL, there is no additional data
  *                      If this is \c NULL, there is no additional data
@@ -320,6 +358,11 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
  * This function automatically reseeds if the reseed counter is exceeded
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
  * or prediction resistance is enabled.
  *
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
  * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
  *                      #mbedtls_hmac_drbg_context structure.
  *                      #mbedtls_hmac_drbg_context structure.
  * \param output        The buffer to fill.
  * \param output        The buffer to fill.
@@ -349,7 +392,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
  *
  *
  * This function automatically reseeds if the reseed counter is exceeded
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
  * or prediction resistance is enabled.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      it is safe to call mbedtls_ctr_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
  * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
  *                      #mbedtls_hmac_drbg_context structure.
  *                      #mbedtls_hmac_drbg_context structure.
  * \param output        The buffer to fill.
  * \param output        The buffer to fill.

+ 15 - 3
thirdparty/mbedtls/include/mbedtls/net_sockets.h

@@ -151,6 +151,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char
  *
  *
  * \return         0 if successful, or one of:
  * \return         0 if successful, or one of:
  *                      MBEDTLS_ERR_NET_SOCKET_FAILED,
  *                      MBEDTLS_ERR_NET_SOCKET_FAILED,
+ *                      MBEDTLS_ERR_NET_UNKNOWN_HOST,
  *                      MBEDTLS_ERR_NET_BIND_FAILED,
  *                      MBEDTLS_ERR_NET_BIND_FAILED,
  *                      MBEDTLS_ERR_NET_LISTEN_FAILED
  *                      MBEDTLS_ERR_NET_LISTEN_FAILED
  *
  *
@@ -170,6 +171,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
  *                  can be NULL if client_ip is null
  *                  can be NULL if client_ip is null
  *
  *
  * \return          0 if successful, or
  * \return          0 if successful, or
+ *                  MBEDTLS_ERR_NET_SOCKET_FAILED,
+ *                  MBEDTLS_ERR_NET_BIND_FAILED,
  *                  MBEDTLS_ERR_NET_ACCEPT_FAILED, or
  *                  MBEDTLS_ERR_NET_ACCEPT_FAILED, or
  *                  MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
  *                  MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
  *                  MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
  *                  MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
@@ -182,6 +185,10 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
 /**
 /**
  * \brief          Check and wait for the context to be ready for read/write
  * \brief          Check and wait for the context to be ready for read/write
  *
  *
+ * \note           The current implementation of this function uses
+ *                 select() and returns an error if the file descriptor
+ *                 is \c FD_SETSIZE or greater.
+ *
  * \param ctx      Socket to check
  * \param ctx      Socket to check
  * \param rw       Bitflag composed of MBEDTLS_NET_POLL_READ and
  * \param rw       Bitflag composed of MBEDTLS_NET_POLL_READ and
  *                 MBEDTLS_NET_POLL_WRITE specifying the events
  *                 MBEDTLS_NET_POLL_WRITE specifying the events
@@ -263,16 +270,21 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len );
  *                 'timeout' seconds. If no error occurs, the actual amount
  *                 'timeout' seconds. If no error occurs, the actual amount
  *                 read is returned.
  *                 read is returned.
  *
  *
+ * \note           The current implementation of this function uses
+ *                 select() and returns an error if the file descriptor
+ *                 is \c FD_SETSIZE or greater.
+ *
  * \param ctx      Socket
  * \param ctx      Socket
  * \param buf      The buffer to write to
  * \param buf      The buffer to write to
  * \param len      Maximum length of the buffer
  * \param len      Maximum length of the buffer
  * \param timeout  Maximum number of milliseconds to wait for data
  * \param timeout  Maximum number of milliseconds to wait for data
  *                 0 means no timeout (wait forever)
  *                 0 means no timeout (wait forever)
  *
  *
- * \return         the number of bytes received,
- *                 or a non-zero error code:
- *                 MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out,
+ * \return         The number of bytes received if successful.
+ *                 MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
  *                 MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
  *                 MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
+ *                 Another negative error code (MBEDTLS_ERR_NET_xxx)
+ *                 for other failures.
  *
  *
  * \note           This function will block (until data becomes available or
  * \note           This function will block (until data becomes available or
  *                 timeout is reached) even if the socket is set to
  *                 timeout is reached) even if the socket is set to

+ 5 - 1
thirdparty/mbedtls/include/mbedtls/rsa.h

@@ -124,7 +124,10 @@ extern "C" {
  */
  */
 typedef struct mbedtls_rsa_context
 typedef struct mbedtls_rsa_context
 {
 {
-    int ver;                    /*!<  Always 0.*/
+    int ver;                    /*!<  Reserved for internal purposes.
+                                 *    Do not set this field in application
+                                 *    code. Its meaning might change without
+                                 *    notice. */
     size_t len;                 /*!<  The size of \p N in Bytes. */
     size_t len;                 /*!<  The size of \p N in Bytes. */
 
 
     mbedtls_mpi N;              /*!<  The public modulus. */
     mbedtls_mpi N;              /*!<  The public modulus. */
@@ -154,6 +157,7 @@ typedef struct mbedtls_rsa_context
                                      mask generating function used in the
                                      mask generating function used in the
                                      EME-OAEP and EMSA-PSS encodings. */
                                      EME-OAEP and EMSA-PSS encodings. */
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
+    /* Invariant: the mutex is initialized iff ver != 0. */
     mbedtls_threading_mutex_t mutex;    /*!<  Thread-safety mutex. */
     mbedtls_threading_mutex_t mutex;    /*!<  Thread-safety mutex. */
 #endif
 #endif
 }
 }

+ 3 - 0
thirdparty/mbedtls/include/mbedtls/threading.h

@@ -73,6 +73,9 @@ extern "C" {
 typedef struct mbedtls_threading_mutex_t
 typedef struct mbedtls_threading_mutex_t
 {
 {
     pthread_mutex_t mutex;
     pthread_mutex_t mutex;
+    /* is_valid is 0 after a failed init or a free, and nonzero after a
+     * successful init. This field is not considered part of the public
+     * API of Mbed TLS and may change without notice. */
     char is_valid;
     char is_valid;
 } mbedtls_threading_mutex_t;
 } mbedtls_threading_mutex_t;
 #endif
 #endif

+ 4 - 4
thirdparty/mbedtls/include/mbedtls/version.h

@@ -65,16 +65,16 @@
  */
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  16
 #define MBEDTLS_VERSION_MINOR  16
-#define MBEDTLS_VERSION_PATCH  9
+#define MBEDTLS_VERSION_PATCH  10
 
 
 /**
 /**
  * The single version number has the following structure:
  * The single version number has the following structure:
  *    MMNNPP00
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  *    Major version | Minor version | Patch version
  */
  */
-#define MBEDTLS_VERSION_NUMBER         0x02100900
-#define MBEDTLS_VERSION_STRING         "2.16.9"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.9"
+#define MBEDTLS_VERSION_NUMBER         0x02100A00
+#define MBEDTLS_VERSION_STRING         "2.16.10"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.10"
 
 
 #if defined(MBEDTLS_VERSION_C)
 #if defined(MBEDTLS_VERSION_C)
 
 

+ 120 - 11
thirdparty/mbedtls/library/base64.c

@@ -96,6 +96,99 @@ static const unsigned char base64_dec_map[128] =
 
 
 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
 
 
+/*
+ * Constant flow conditional assignment to unsigned char
+ */
+static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
+                                       unsigned char condition )
+{
+    /* MSVC has a warning about unary minus on unsigned integer types,
+     * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+    /* Generate bitmask from condition, mask will either be 0xFF or 0 */
+    unsigned char mask = ( condition | -condition );
+    mask >>= 7;
+    mask = -mask;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+    *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
+}
+
+/*
+ * Constant flow conditional assignment to uint_32
+ */
+static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
+                                       uint32_t condition )
+{
+    /* MSVC has a warning about unary minus on unsigned integer types,
+     * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+    /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
+    uint32_t mask = ( condition | -condition );
+    mask >>= 31;
+    mask = -mask;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+    *dest = ( src & mask ) | ( ( *dest ) & ~mask );
+}
+
+/*
+ * Constant flow check for equality
+ */
+static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
+{
+    size_t difference = in_a ^ in_b;
+
+    /* MSVC has a warning about unary minus on unsigned integer types,
+     * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+
+    difference |= -difference;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+    /* cope with the varying size of size_t per platform */
+    difference >>= ( sizeof( difference ) * 8 - 1 );
+
+    return (unsigned char) ( 1 ^ difference );
+}
+
+/*
+ * Constant flow lookup into table.
+ */
+static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
+                                                 const size_t table_size, const size_t table_index )
+{
+    size_t i;
+    unsigned char result = 0;
+
+    for( i = 0; i < table_size; ++i )
+    {
+        mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
+    }
+
+    return result;
+}
+
 /*
 /*
  * Encode a buffer into base64 format
  * Encode a buffer into base64 format
  */
  */
@@ -136,10 +229,17 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
         C2 = *src++;
         C2 = *src++;
         C3 = *src++;
         C3 = *src++;
 
 
-        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
-        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
-        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
-        *p++ = base64_enc_map[C3 & 0x3F];
+        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                            ( ( C1 >> 2 ) & 0x3F ) );
+
+        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                            ( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
+
+        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                            ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
+
+        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                            ( C3 & 0x3F ) );
     }
     }
 
 
     if( i < slen )
     if( i < slen )
@@ -147,11 +247,15 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
         C1 = *src++;
         C1 = *src++;
         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
 
 
-        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
-        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                            ( ( C1 >> 2 ) & 0x3F ) );
+
+        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                            ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
 
 
         if( ( i + 1 ) < slen )
         if( ( i + 1 ) < slen )
-             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+             *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+                                                 ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
         else *p++ = '=';
         else *p++ = '=';
 
 
         *p++ = '=';
         *p++ = '=';
@@ -172,6 +276,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
     size_t i, n;
     size_t i, n;
     uint32_t j, x;
     uint32_t j, x;
     unsigned char *p;
     unsigned char *p;
+    unsigned char dec_map_lookup;
 
 
     /* First pass: check for validity and get output length */
     /* First pass: check for validity and get output length */
     for( i = n = j = 0; i < slen; i++ )
     for( i = n = j = 0; i < slen; i++ )
@@ -202,10 +307,12 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
         if( src[i] == '=' && ++j > 2 )
         if( src[i] == '=' && ++j > 2 )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
 
-        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+        dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
+
+        if( src[i] > 127 || dec_map_lookup == 127 )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
 
-        if( base64_dec_map[src[i]] < 64 && j != 0 )
+        if( dec_map_lookup < 64 && j != 0 )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
 
         n++;
         n++;
@@ -235,8 +342,10 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
         if( *src == '\r' || *src == '\n' || *src == ' ' )
         if( *src == '\r' || *src == '\n' || *src == ' ' )
             continue;
             continue;
 
 
-        j -= ( base64_dec_map[*src] == 64 );
-        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
+        dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
+
+        mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
+        x  = ( x << 6 ) | ( dec_map_lookup & 0x3F );
 
 
         if( ++n == 4 )
         if( ++n == 4 )
         {
         {

+ 6 - 0
thirdparty/mbedtls/library/bignum.c

@@ -1354,6 +1354,12 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
     for( n = B->n; n > 0; n-- )
     for( n = B->n; n > 0; n-- )
         if( B->p[n - 1] != 0 )
         if( B->p[n - 1] != 0 )
             break;
             break;
+    if( n > A->n )
+    {
+        /* B >= (2^ciL)^n > A */
+        ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
+        goto cleanup;
+    }
 
 
     carry = mpi_sub_hlp( n, X->p, B->p );
     carry = mpi_sub_hlp( n, X->p, B->p );
     if( carry != 0 )
     if( carry != 0 )

+ 8 - 8
thirdparty/mbedtls/library/ctr_drbg.c

@@ -83,10 +83,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
 
 
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 }
 
 
 /*
 /*
@@ -99,14 +95,13 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
         return;
         return;
 
 
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    /* The mutex is initialized iff f_entropy is set. */
+    if( ctx->f_entropy != NULL )
+        mbedtls_mutex_free( &ctx->mutex );
 #endif
 #endif
     mbedtls_aes_free( &ctx->aes_ctx );
     mbedtls_aes_free( &ctx->aes_ctx );
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 }
 
 
 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
@@ -422,6 +417,11 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
 
 
     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
 
 
+    /* The mutex is initialized iff f_entropy is set. */
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+
     mbedtls_aes_init( &ctx->aes_ctx );
     mbedtls_aes_init( &ctx->aes_ctx );
 
 
     ctx->f_entropy = f_entropy;
     ctx->f_entropy = f_entropy;

+ 8 - 0
thirdparty/mbedtls/library/ecdsa.c

@@ -247,6 +247,9 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
 
 
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
 
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
+    !defined(MBEDTLS_ECDSA_SIGN_ALT)     || \
+    !defined(MBEDTLS_ECDSA_VERIFY_ALT)
 /*
 /*
  * Derive a suitable integer for group grp from a buffer of length len
  * Derive a suitable integer for group grp from a buffer of length len
  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@@ -269,6 +272,7 @@ static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
 cleanup:
 cleanup:
     return( ret );
     return( ret );
 }
 }
+#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
 
 
 #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
 #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
 /*
 /*
@@ -780,6 +784,8 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
     (void) md_alg;
     (void) md_alg;
 
 
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
+    (void) rs_ctx;
+
     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
                          hash, hlen, f_rng, p_rng ) );
                          hash, hlen, f_rng, p_rng ) );
 #else
 #else
@@ -888,6 +894,8 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
         goto cleanup;
         goto cleanup;
     }
     }
 #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
 #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
+    (void) rs_ctx;
+
     if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
     if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
                                       &ctx->Q, &r, &s ) ) != 0 )
                                       &ctx->Q, &r, &s ) ) != 0 )
         goto cleanup;
         goto cleanup;

+ 11 - 0
thirdparty/mbedtls/library/ecjpake.c

@@ -850,6 +850,8 @@ static const unsigned char ecjpake_test_password[] = {
     0x65, 0x73, 0x74
     0x65, 0x73, 0x74
 };
 };
 
 
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+
 static const unsigned char ecjpake_test_x1[] = {
 static const unsigned char ecjpake_test_x1[] = {
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
     0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
     0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
@@ -994,6 +996,8 @@ cleanup:
     return( ret );
     return( ret );
 }
 }
 
 
+#endif /* ! MBEDTLS_ECJPAKE_ALT */
+
 /* For tests we don't need a secure RNG;
 /* For tests we don't need a secure RNG;
  * use the LGC from Numerical Recipes for simplicity */
  * use the LGC from Numerical Recipes for simplicity */
 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
@@ -1089,6 +1093,12 @@ int mbedtls_ecjpake_self_test( int verbose )
     if( verbose != 0 )
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
         mbedtls_printf( "passed\n" );
 
 
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+    /* 'reference handshake' tests can only be run against implementations
+     * for which we have 100% control over how the random ephemeral keys
+     * are generated. This is only the case for the internal mbed TLS
+     * implementation, so these tests are skipped in case the internal
+     * implementation is swapped out for an alternative one. */
     if( verbose != 0 )
     if( verbose != 0 )
         mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
         mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
 
 
@@ -1137,6 +1147,7 @@ int mbedtls_ecjpake_self_test( int verbose )
 
 
     if( verbose != 0 )
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
         mbedtls_printf( "passed\n" );
+#endif /* ! MBEDTLS_ECJPAKE_ALT */
 
 
 cleanup:
 cleanup:
     mbedtls_ecjpake_free( &cli );
     mbedtls_ecjpake_free( &cli );

+ 6 - 1
thirdparty/mbedtls/library/entropy.c

@@ -146,6 +146,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
 
 
 void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
 void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
 {
 {
+    /* If the context was already free, don't call free() again.
+     * This is important for mutexes which don't allow double-free. */
+    if( ctx->accumulator_started == -1 )
+        return;
+
 #if defined(MBEDTLS_HAVEGE_C)
 #if defined(MBEDTLS_HAVEGE_C)
     mbedtls_havege_free( &ctx->havege_data );
     mbedtls_havege_free( &ctx->havege_data );
 #endif
 #endif
@@ -162,7 +167,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
 #endif
 #endif
     ctx->source_count = 0;
     ctx->source_count = 0;
     mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
     mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
-    ctx->accumulator_started = 0;
+    ctx->accumulator_started = -1;
 }
 }
 
 
 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,

+ 12 - 8
thirdparty/mbedtls/library/hmac_drbg.c

@@ -84,10 +84,6 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
 
 
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 }
 
 
 /*
 /*
@@ -159,6 +155,10 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
         return( ret );
         return( ret );
 
 
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+
     /*
     /*
      * Set initial working state.
      * Set initial working state.
      * Use the V memory location, which is currently all 0, to initialize the
      * Use the V memory location, which is currently all 0, to initialize the
@@ -284,6 +284,11 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
         return( ret );
         return( ret );
 
 
+    /* The mutex is initialized iff the md context is set up. */
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+
     md_size = mbedtls_md_get_size( md_info );
     md_size = mbedtls_md_get_size( md_info );
 
 
     /*
     /*
@@ -451,14 +456,13 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
         return;
         return;
 
 
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    /* The mutex is initialized iff the md context is set up. */
+    if( ctx->md_ctx.md_info != NULL )
+        mbedtls_mutex_free( &ctx->mutex );
 #endif
 #endif
     mbedtls_md_free( &ctx->md_ctx );
     mbedtls_md_free( &ctx->md_ctx );
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 }
 
 
 #if defined(MBEDTLS_FS_IO)
 #if defined(MBEDTLS_FS_IO)

+ 14 - 0
thirdparty/mbedtls/library/net_sockets.c

@@ -496,6 +496,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
     if( fd < 0 )
     if( fd < 0 )
         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
 
 
+    /* A limitation of select() is that it only works with file descriptors
+     * that are strictly less than FD_SETSIZE. This is a limitation of the
+     * fd_set type. Error out early, because attempting to call FD_SET on a
+     * large file descriptor is a buffer overflow on typical platforms. */
+    if( fd >= FD_SETSIZE )
+        return( MBEDTLS_ERR_NET_POLL_FAILED );
+
 #if defined(__has_feature)
 #if defined(__has_feature)
 #if __has_feature(memory_sanitizer)
 #if __has_feature(memory_sanitizer)
     /* Ensure that memory sanitizers consider read_fds and write_fds as
     /* Ensure that memory sanitizers consider read_fds and write_fds as
@@ -615,6 +622,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
     if( fd < 0 )
     if( fd < 0 )
         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
 
 
+    /* A limitation of select() is that it only works with file descriptors
+     * that are strictly less than FD_SETSIZE. This is a limitation of the
+     * fd_set type. Error out early, because attempting to call FD_SET on a
+     * large file descriptor is a buffer overflow on typical platforms. */
+    if( fd >= FD_SETSIZE )
+        return( MBEDTLS_ERR_NET_POLL_FAILED );
+
     FD_ZERO( &read_fds );
     FD_ZERO( &read_fds );
     FD_SET( fd, &read_fds );
     FD_SET( fd, &read_fds );
 
 

+ 11 - 11
thirdparty/mbedtls/library/pkwrite.c

@@ -455,7 +455,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
  *  }
  *  }
  */
  */
-#define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE
+#define RSA_PUB_DER_MAX_BYTES   ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE )
 
 
 /*
 /*
  * RSA private keys:
  * RSA private keys:
@@ -472,10 +472,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
  *  }
  *  }
  */
  */
-#define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \
-                                MBEDTLS_MPI_MAX_SIZE % 2
-#define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \
-                                   + 5 * MPI_MAX_SIZE_2
+#define MPI_MAX_SIZE_2          ( MBEDTLS_MPI_MAX_SIZE / 2 + \
+                                  MBEDTLS_MPI_MAX_SIZE % 2 )
+#define RSA_PRV_DER_MAX_BYTES   ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+                                   + 5 * MPI_MAX_SIZE_2 )
 
 
 #else /* MBEDTLS_RSA_C */
 #else /* MBEDTLS_RSA_C */
 
 
@@ -496,7 +496,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
  *                                            + 2 * ECP_MAX (coords)    [1]
  *                                            + 2 * ECP_MAX (coords)    [1]
  *  }
  *  }
  */
  */
-#define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES
+#define ECP_PUB_DER_MAX_BYTES   ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
 
 
 /*
 /*
  * EC private keys:
  * EC private keys:
@@ -507,7 +507,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
  *    }
  *    }
  */
  */
-#define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES
+#define ECP_PRV_DER_MAX_BYTES   ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
 
 
 #else /* MBEDTLS_ECP_C */
 #else /* MBEDTLS_ECP_C */
 
 
@@ -516,10 +516,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
 
 
 #endif /* MBEDTLS_ECP_C */
 #endif /* MBEDTLS_ECP_C */
 
 
-#define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
-                            RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
-#define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
-                            RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
+#define PUB_DER_MAX_BYTES   ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
+                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES )
+#define PRV_DER_MAX_BYTES   ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
+                              RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES )
 
 
 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
 {
 {

+ 20 - 8
thirdparty/mbedtls/library/rsa.c

@@ -520,6 +520,9 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
     mbedtls_rsa_set_padding( ctx, padding, hash_id );
     mbedtls_rsa_set_padding( ctx, padding, hash_id );
 
 
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
+    /* Set ctx->ver to nonzero to indicate that the mutex has been
+     * initialized and will need to be freed. */
+    ctx->ver = 1;
     mbedtls_mutex_init( &ctx->mutex );
     mbedtls_mutex_init( &ctx->mutex );
 #endif
 #endif
 }
 }
@@ -567,9 +570,6 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
     RSA_VALIDATE_RET( ctx != NULL );
     RSA_VALIDATE_RET( ctx != NULL );
     RSA_VALIDATE_RET( f_rng != NULL );
     RSA_VALIDATE_RET( f_rng != NULL );
 
 
-    if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
     /*
     /*
      * If the modulus is 1024 bit long or shorter, then the security strength of
      * If the modulus is 1024 bit long or shorter, then the security strength of
      * the RSA algorithm is less than or equal to 80 bits and therefore an error
      * the RSA algorithm is less than or equal to 80 bits and therefore an error
@@ -582,6 +582,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
     mbedtls_mpi_init( &G );
     mbedtls_mpi_init( &G );
     mbedtls_mpi_init( &L );
     mbedtls_mpi_init( &L );
 
 
+    if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
+    {
+        ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
     /*
     /*
      * find primes P and Q with Q < P so that:
      * find primes P and Q with Q < P so that:
      * 1.  |P-Q| > 2^( nbits / 2 - 100 )
      * 1.  |P-Q| > 2^( nbits / 2 - 100 )
@@ -659,7 +665,9 @@ cleanup:
     if( ret != 0 )
     if( ret != 0 )
     {
     {
         mbedtls_rsa_free( ctx );
         mbedtls_rsa_free( ctx );
-        return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
+        if( ( -ret & ~0x7f ) == 0 )
+            ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret;
+        return( ret );
     }
     }
 
 
     return( 0 );
     return( 0 );
@@ -1106,10 +1114,10 @@ cleanup:
     mbedtls_mpi_free( &C );
     mbedtls_mpi_free( &C );
     mbedtls_mpi_free( &I );
     mbedtls_mpi_free( &I );
 
 
-    if( ret != 0 )
+    if( ret != 0 && ret >= -0x007f )
         return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
         return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
 
 
-    return( 0 );
+    return( ret );
 }
 }
 
 
 #if defined(MBEDTLS_PKCS1_V21)
 #if defined(MBEDTLS_PKCS1_V21)
@@ -2502,7 +2510,6 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
     RSA_VALIDATE_RET( dst != NULL );
     RSA_VALIDATE_RET( dst != NULL );
     RSA_VALIDATE_RET( src != NULL );
     RSA_VALIDATE_RET( src != NULL );
 
 
-    dst->ver = src->ver;
     dst->len = src->len;
     dst->len = src->len;
 
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
@@ -2561,7 +2568,12 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
 #endif /* MBEDTLS_RSA_NO_CRT */
 #endif /* MBEDTLS_RSA_NO_CRT */
 
 
 #if defined(MBEDTLS_THREADING_C)
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    /* Free the mutex, but only if it hasn't been freed already. */
+    if( ctx->ver != 0 )
+    {
+        mbedtls_mutex_free( &ctx->mutex );
+        ctx->ver = 0;
+    }
 #endif
 #endif
 }
 }
 
 

+ 6 - 0
thirdparty/mbedtls/library/threading.c

@@ -98,6 +98,12 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
     if( mutex == NULL )
     if( mutex == NULL )
         return;
         return;
 
 
+    /* A nonzero value of is_valid indicates a successfully initialized
+     * mutex. This is a workaround for not being able to return an error
+     * code for this function. The lock/unlock functions return an error
+     * if is_valid is nonzero. The Mbed TLS unit test code uses this field
+     * to distinguish more states of the mutex; see helpers.function for
+     * details. */
     mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
     mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
 }
 }
 
 

+ 3 - 0
thirdparty/mbedtls/library/version_features.c

@@ -553,6 +553,9 @@ static const char *features[] = {
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT)
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT)
     "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT",
     "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT",
 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */
 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */
+#if defined(MBEDTLS_TEST_HOOKS)
+    "MBEDTLS_TEST_HOOKS",
+#endif /* MBEDTLS_TEST_HOOKS */
 #if defined(MBEDTLS_THREADING_ALT)
 #if defined(MBEDTLS_THREADING_ALT)
     "MBEDTLS_THREADING_ALT",
     "MBEDTLS_THREADING_ALT",
 #endif /* MBEDTLS_THREADING_ALT */
 #endif /* MBEDTLS_THREADING_ALT */