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

Cherry-picks for the 3.2 branch (future 3.2.4) - 29th batch
This commit is contained in:
Rémi Verschelde 2021-03-14 15:44:58 +01:00 committed by GitHub
commit 6a9e7c5a53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 552 additions and 173 deletions

View file

@ -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():

View file

@ -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(!p_dst, -1);
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode."); 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;

View file

@ -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++) {

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

@ -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) {

View file

@ -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();

View file

@ -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) {

View file

@ -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();

View file

@ -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(); Node *scene_root = editor_data.get_edited_scene_root(tab_closing);
save_confirmation->get_ok()->set_text(TTR("Save & Close")); if (scene_root) {
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene")); String scene_filename = scene_root->get_filename();
save_confirmation->popup_centered_minsize(); save_confirmation->get_ok()->set_text(TTR("Save & Close"));
break; 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();

View file

@ -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");

View file

@ -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);

View file

@ -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() {

View file

@ -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);
{ _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);
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]);
}
}
repository->connect("item_selected", this, "_repository_changed"); repository->connect("item_selected", this, "_repository_changed");

View file

@ -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;

View file

@ -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")) {

View file

@ -635,8 +635,7 @@ void SceneTreeEditor::_selected_changed() {
} }
void SceneTreeEditor::_deselect_items() { void SceneTreeEditor::_deselect_items() {
// Clear currently selected items in scene tree dock.
// Clear currently elected 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);

View file

@ -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

View file

@ -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; handle_cmdline_options(glue_dir_path, cs_dir_path, cpp_dir_path);
bindings_generator.set_log_print_enabled(true); exit_godot = 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.");
}
if (exit_godot) {
// Exit once done // Exit once done
Main::cleanup(true); Main::cleanup(true);
::exit(0); ::exit(0);

View file

@ -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) ERR_FAIL_NULL_V_MSG(*r_value, -1, "Out of memory.");
return -1;
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);
} }

View file

@ -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;

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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); dev_list = (PRAWINPUTDEVICELIST)memalloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
if (!dev_list) return false; 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;
} }

View file

@ -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);

View file

@ -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();

View file

@ -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();

View file

@ -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_RGB_img(const Ref<Image> &p_rgb_img);
void set_YCbCr_img(Ref<Image> p_ycbcr_img); void set_YCbCr_img(const Ref<Image> &p_ycbcr_img);
void set_YCbCr_imgs(Ref<Image> p_y_img, Ref<Image> p_cbcr_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();

View file

@ -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:

View file

@ -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
* *

View file

@ -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.

View file

@ -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;

View file

@ -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.

View file

@ -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, * \return The number of bytes received if successful.
* or a non-zero error code: * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
* 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

View file

@ -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
} }

View file

@ -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

View file

@ -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_NUMBER 0x02100A00
#define MBEDTLS_VERSION_STRING "2.16.9" #define MBEDTLS_VERSION_STRING "2.16.10"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.9" #define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.10"
#if defined(MBEDTLS_VERSION_C) #if defined(MBEDTLS_VERSION_C)

View file

@ -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++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; ( ( C1 >> 2 ) & 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 & 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++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; ( ( 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 ); dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
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 )
{ {

View file

@ -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 )

View file

@ -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;

View file

@ -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;

View file

@ -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 );

View file

@ -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,

View file

@ -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)

View file

@ -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 );

View file

@ -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 + \ #define MPI_MAX_SIZE_2 ( MBEDTLS_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 \ #define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+ 5 * MPI_MAX_SIZE_2 + 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 ? \ #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 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 ? \ #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 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 )
{ {

View file

@ -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
} }

View file

@ -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;
} }

View file

@ -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 */